The Infamous Double-Hop Problem in PowerShell

The Infamous Double-Hop Problem in PowerShell

In this article, we will discuss how to get around the infamous double-hop problem in PowerShell. It's easier than you think.

When you're in a PowerShell Remoting session and attempt to access a resource outside of that remote computer, you may run into an Access Denied error message. You've already authenticated to the remote session with your username and password, and you have permission to access the network resource you're connecting to. It can be frustrating.

Below is an example of what you may run into.

Using PowerShell Remoting to Connect to a SRV1 Computer

In this example, we're using PowerShell Remoting to connect to the SRV1 computer. While in that session, we're then attempting to browse files on the root of the C drive on the SRV2 computer. It's not working out too well though.

PS> Invoke-Command -ComputerName SRV1 -ScriptBlock { Get-ChildItem -Path \\SRV2\c$ }
Access is denied
    + CategoryInfo          : PermissionDenied: (\\SRV2\c$:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : SRV1

Cannot find path '\\SRV2\c$' because it does not exist.
    + CategoryInfo          : ObjectNotFound: (\\SRV2\c$:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : SRV1

This example isn't working because PowerShell isn't seamlessly passing the credential we authenticated with (in this case using Kerberos) to the remote resource. This isn't a bug but a security feature.


If you Google this error (Cannot find path '\\SRV2\c$' because it does not exist), you'll find lots of examples of people "solving" it by using CredSSP. This is supposed to be insecure and also requires additional configuration ahead of time. I recently discovered a new way to solve this problem which uses session configurations. This "new" way allows you to tie a credential to a PowerShell session configuration and reuse this configuration for all future connections.

Let's see how we can fix this without using CredSSP. First, we'll connect to the SRV1 computer again and register a session configuration on it using a a domain account. This ensures that when we connect using this session configuration, it will always authenticate with this user.

Invoke-Command -ComputerName SRV1 -ScriptBlock { Register-PSSessionConfiguration -Name Ipswitch -RunAsCredential 'lab.local\account' -Force }

Once we have the session configuration created, we can then just specify that session configuration using the ConfigurationName parameter. This then forces PowerShell to use the domain account I provided earlier. You can see below that I now can successfully browse to the network resource from within the remote SRV1 session.

PS> Invoke-Command -ComputerName 'SRV1' -ScriptBlock { Get-ChildItem -Path \\SRV2\c$ } -ConfigurationName Ipswitch.

    Directory: \\SRV1\c$

Mode                LastWriteTime         Length Name                                                                 PSComputerName
----                -------------         ------ ----                                                                 --------------
d-----       11/30/2016  11:35 AM                Program Files                                                        SRV1
d-----        5/25/2017  11:32 AM                Windows                                                              SRV1

Notice that we didn't have to use the Authenticate parameter to specify CredSSP. The only parameter we need to use is ConfigurationName and specify the name of the session configuration I had created on the SRV1 computer.

This method is a great alternative to using the known insecure method of using CredSSP. It allows you to use native tooling without a lot of workarounds. The only caveat is that you must always remember to use the ConfigurationName parameter every time. But, you'd have to remember to use the Authentication parameter every time anyway when using CredSSP.

If you wanted to, you could always use $PSDefaultParameterValues = @{'Invoke-Command:ConfigurationName'='Ipswitch' } to default that parameter value, but if you're like me you might forget you're using that parameter value for every Invoke-Command call!


Related Posts

Comments are disabled in preview mode.
Loading animation