cmdlet How to upload and download files with PowerShell FTP script
X

How to avoid the double-hop problem with PowerShell

IT pros who manage with PowerShell will run into the double-hop problem and use CredSSP to work around it. This tutorial offers a more streamlined way to avoid that roadblock.

Editor's note: Adam Bertram originally wrote the article and Stephen J. Bigelow updated it.

PowerShell remoting works great to manage remote servers, until you run headfirst into the dreaded double-hop problem.

In a typical scenario, you're working on one remote machine, then attempt to run a PowerShell command against a different server, but get hit with an access denied message. A typical double hop can occur when the following situation develops:

  • An administrator logs into Server 1.
  • Once in Server 1, the administrator starts a remote PowerShell session and connects to Server 2.
  • A command executed on Server 2 (through PowerShell remoting) tries to access Server 3.

In this type of situation, access to the resources of Server 3 is blocked because the credentials used to form the PowerShell remote connection between Server 1 and Server 2 are not passed to Server 3. You can use CredSSP to get around this double-hop problem, but there's a better solution you can try.

Why the double-hop problem happens

After you connect to a remote computer with PowerShell remoting and attempt to issue commands to a resource outside that computer, you might receive the following message:

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

You might think it should have worked because you authenticated credentials on the remote computer and those credentials have permissions to access the second remote computer. However, Active Directory domains use Kerberos for authentication, which does not allow passing credentials beyond the first machine to prevent malicious activity.

Some administrators solve the double-hop problem with CredSSP, which is a less-secure method that requires some additional configuration work. But there is another option. You can tie a credential to a PowerShell session configuration and reuse the configuration for all future connections.

Set new PowerShell session configurations to accept credentials

For this example, we will work with a server named SRV1 and create a new session configuration on this machine using the Register-PSSessionConfiguration cmdlet. The following command creates a session called Demo and uses the RunAsCredential parameter to run the session.

Invoke-Command -ComputerName SRV1 -ScriptBlock { Register-PSSessionConfiguration -Name Demo -RunAsCredential 'domain\mydomainaccount' -Force }
RunAsCredential parameter warning
PowerShell returns this warning about the RunAsCredential parameter.

This command creates a new session configuration on the remote computer and, when connected, forces it to always run with the credential provided.

Next, specify the configuration with the ConfigurationName parameter when running Invoke-Command. Use the same command as above, but with the Demo configuration. Use this session configuration the next time you run a command on a remote computer that connects to a third computer.

Invoke-Command -ComputerName 'SRV1' -ScriptBlock { Get-ChildItem -Path \\SRV2\c$ } -ConfigurationName Demo

    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
<snip>

Instead of an access denied message, the command runs as expected. There's no need to use CredSSP roles on the client or the server to avoid the double-hop problem. The configuration will stay indefinitely on the remote server. Just use the ConfigurationName parameter each time you use Invoke-Command or Enter-PSSession.

Automatically invoke the ConfigurationName parameter

Now that we've solved this PowerShell remoting issue, you can make it work in a more streamlined fashion. With the $PSDefaultParameterValues automatic variable, you can avoid using the ConfigurationName parameter each time. You can program PowerShell to use a certain parameter when using a specific command.

Use the ConfigurationName parameter and specify the value of the session Demo every time you call Invoke-Command. To do that, create the $PSDefaultParameterValues hash table and assign it a key of Invoke-Command:ConfigurationName and a value of Demo as shown in the following:

$PSDefaultParameterValues = @{'Invoke-Command:ConfigurationName'='Demo' }

All these techniques should help you work more efficiently when using PowerShell to work with remote machines.

Other solutions to the double-hop problem

CredSSP is typically regarded as the easiest and most balanced means of overcoming the PowerShell double-hop problem, but other solutions or workarounds are also available including the following:

  • Kerberos constrained delegation offers better security but requires a Domain Administrator before it can be used.
  • Kerberos resource-based constrained delegation offers better security and simpler configuration if the Kerberos is in use.
  • Just Enough Administration (JEA) techniques can provide great security but demand detailed configuration efforts.

Other techniques here such as PSSessionConfiguration and passing credentials inside an Invoke-Command script block are relatively simple to configure and use. However, both require careful credential management, which can be tricky for small businesses or inexperienced administrators.

Next Steps

Build a PowerShell logging function for troubleshooting

What's new with PowerShell error handling?

Dig Deeper on IT operations and infrastructure management