One of the most annoying problems that has existed with PowerShell ever since we got PowerShell remoting in v2 is the infamous double-hop or multi-hop problem. This occurs if you try connect to another remote computer from within your remote session.
Avatar

Using PowerShell remoting, we can seamlessly connect to a remote computer and run commands on it just like we can on our local computer. PowerShell remoting is similar to psexec in that manner. Once set up, this functionality works great. But you'll soon find it doesn't work so great once you attempt to access network resources from that same remoting session.

To demonstrate, let's say I have three machines: CLIENT1, SRV1, and SRV2 all on the same Active Directory domain. On CLIENT1, I run a command on SRV2 using Invoke-Commmand, which uses PowerShell remoting.

PS> Invoke-Command -ComputerName SRV1 -ScriptBlock { "Yay! I'm on the $(hostname) server!" }
Yay! I'm on the SRV1 server!

That works great, but now let's try to list some files on the SRV2 server where I know I have rights to do so from the session on the SRV1 server.

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

It rejected me. The reason is because PowerShell remoting doesn't allow us to pass the credential we inherently used to establish a session with SRV1. When we attempt to connect to SRV2 somehow, it passes no credentials and thus denies us.

If you Google this error, 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 that 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.

To demonstate, let's first connect to SRV1 again but this time register a session configuration on the server using a domain account.

Invoke-Command -ComputerName SRV1 -ScriptBlock { Register-PSSessionConfiguration -Name 4SysOps -RunAsCredential 'domain\mydomainaccount' -Force }

Now I'll use this session configuration the next time I want to run a command on the remote computer that connects to a third computer.

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

    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>
Solving the PowerShell double hop problem with session configurations

Solving the PowerShell double hop problem with session configurations

It works without CredSSP! At this point, you can continue to use Invoke-Command at will without worrying about the multi-hop problem. Just remember to use the ConfigurationName parameter to specify the configuration you've got running under your domain account! Even better, you could just add that parameter to $PSDefaultParameterValues and have PowerShell automatically use that parameter every time you call Invoke-Command.

Subscribe to 4sysops newsletter!

$PSDefaultParameterValues = @{'Invoke-Command:ConfigurationName'='4SysOps' }
avataravatar
21 Comments
  1. Avatar
    Harald 6 years ago

    Hi Adam,

    did you read my mind? Thanks for this post!

    I was facing exactly that weird multi-hop issue, and I was thinking about giving that CredSSP stuff a try, when your post hit my inbox (luckily).

    One question: Is registering a PSSessionConfiguration a onetime task (persisted on the remote machine), or do I need to do it every time I create a remote session?

    Thanks,

    Harald

  2. Avatar
    johnM 6 years ago

    Hi.  In your second working example you are calling \\Srv2\C$, but the output example shows Srv1.

    Is that a quirk of Powershell, showing the first hop server name, and the second hop server data?   Or is this an incorrect picture?

  3. Avatar
    Stu 6 years ago

    Hi Adam – Thanks for this post.  Once we register the PSSessionConfiguration on the remote machine what is stopping other users from using the configurationName and potentially gaining elevated privileges?

  4. Avatar
    amnich 6 years ago

    By default only the administrators can use this configuration. So if you as Admin1 create a session configuration with your credentials, let’s say Admin2 can also use this configuration and will act under your credentials.

    You could restrict the usage of your configuration with Set-PSSessionConfiguration only to you, but the other Admin could change it without any problems.

     

  5. Avatar
    Babun 6 years ago

    It really sounds like something you’re not supposed to do..

  6. Avatar
    Babun 6 years ago

    Or at the very least you should maybe discuss the security implications of doing so, and how the exposure might be limited

  7. Avatar
    Nishanth 5 years ago

    Hey Adam, You are a life saver! I lost almost 4 days with these issue. Thanks a lot for this post.

    -Nishanth

  8. Avatar
    Darren 5 years ago

    Kudos to you sir.

    This post solved my multi-hop problem (trying to create Windows Failover cluster on two domain-less Win2016 servers using New-Cluster command from a remote Windows 10 client machine.

    Somebody get this man a whiskey!

    • Avatar
      Ashley 5 years ago

      Hi Darren, im having this issue, can you elabourate more on what you did ?

      • Avatar
        Darren 5 years ago

        this is the key section below that I was battling with – after I worked around the SessionConfiguration issue, then it worked. Good luck sir

         

        # Generate a random name for the SessionConfiguration
        
        $sessionName = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object {[char]$_})
        
        Invoke-Command -ComputerName $servers[0] -Credential $VMcredentials -ScriptBlock {
        
        Register-PSSessionConfiguration -Name $using:sessionName -RunAsCredential $using:VMcredentials -Force -WarningAction SilentlyContinue | Out-Null
        
        } -ErrorAction SilentlyContinue
        
        
        
        start-sleep 3
        
        Invoke-Command -ComputerName $servers[0] -Credential $VMcredentials -ScriptBlock {
        
        New-Cluster -Name $using:clusterName -Node $using:node1,$using:node2 -AdministrativeAccessPoint DNS -StaticAddress $using:clusterIP -NoStorage | Out-Null
        
        } -ConfigurationName $sessionName | out-null

         

        avatar
  9. Avatar
    Simon Norton 5 years ago

    Adam I cannot tell you how much this means to me.  My whole strategy depended on using remote PowerShell sessions from SQL Server Agent Jobs.  I thought I was sunk.  Now I’m running around doing my Happy Dance!

    Thank you, thank you, thank you!

    thank you.

  10. Avatar
    Robert H 4 years ago

    hey Adam, thanks a lot – just as Harald already wrote : "you read my mind".

    Me, too, was searching a lot and always finding these "use CredSSP" – yeah … isn't there a better way? how about security? how about storing passwords into files?

    thanks !

  11. Avatar
    Sean Lancaster 4 years ago

    So you can pass the credential object as a parameter. So you can create the session with your credential, then pass that object into the session itself and use it there.

    $cred = get-credential

    $mySession = New-PSSession -ComputerName $destinationserver -Credential $cred

    $scriptblockContent =

    {

    $myCred = $args[0]

    $Env:ADPS_LoadDefaultDrive = 0

    import-module ActiveDirectory

    get-aduser -Filter * -SearchBase $mySearchBase -Credential $myCred

    }

    invoke-command -Session $mySession -ScriptBlock $scriptBlockContent -ArgumentList ($cred)

  12. Avatar
    Gyanendra 3 years ago

    Thank you so much.. this is the solution i was looking from long time.

  13. Avatar
    Scott L. (Rank 2) 3 years ago

    Thanks Adam, I was in the  'PSRabbitHole'  for a long while in the early days trying to figure this one out, to no avail, so I left it alone until now. Very useful especially when copying data from one endpoint to another and you need for the  processing to happen on the remote machine and not yours… 

  14. Avatar
    JD Gross 3 years ago

    Thank you so much for posting this! Very helpful and informative. I have been looking for an answer to the multi-hop problem for a while now and this is absolutely perfect!

  15. Avatar
    Jan 3 years ago

    Thanks brilliant article.

  16. Avatar
    IT 3 years ago

    So, CredSSP is bad since it is delegating your credential to remote computer when you you running the command and specifying this type of auth and if remote computre is compromised than your credentials can be reused for some not good purpose. Understood. 

    This solution suggests to create persistent PS Session config with domain credential which persists somwhere on the remore machine. So why does it better given the domain credentials are still given to remote machine? Is not it even worse since in case of CredSSP the credentials should be captured during their lifetime in lsass memory while in case of PS session configuration they are present on the remote machine constantly?

    avatar
  17. Avatar
    Robert Golden 3 years ago

    1. Register-PSSessionConfiguration creates such a large security risk Microsoft added the following text… WARNING: When RunAs is enabled in a Windows PowerShell session configuration, the Windows security model cannot enforce a security boundary between different user sessions that are created by using this endpoint.

    2. I was able to sign in as a different AD account and perform commands with the original AD account. I can't put into words how huge of a deal that is. 

    3. The PSSessionConfiguration sticks around even after reboots… 

    4. Why in god's name does this KB not mention how to unregister the PSSessionConfiguration… For those that need it "Unregister-PSSessionConfiguration -Name 4SysOps". 

    avatar
    • Avatar
      Henri 1 year ago

      The “Disallow WinRM from storing RunAs credentials” Group Policy should be use to block this.

  18. Avatar
    Michael D Harlan 2 years ago

    THANK YOU! This is perhaps the most creative solution to the double-hop issue I have ever seen. Bravo!

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account