- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
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>
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' }
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
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?
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?
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.
It really sounds like something you’re not supposed to do..
Or at the very least you should maybe discuss the security implications of doing so, and how the exposure might be limited
Hey Adam, You are a life saver! I lost almost 4 days with these issue. Thanks a lot for this post.
-Nishanth
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!
Hi Darren, im having this issue, can you elabourate more on what you did ?
this is the key section below that I was battling with – after I worked around the SessionConfiguration issue, then it worked. Good luck sir
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.
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 !
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)
Thank you so much.. this is the solution i was looking from long time.
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…
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!
Thanks brilliant article.
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?
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".
The “Disallow WinRM from storing RunAs credentials” Group Policy should be use to block this.
THANK YOU! This is perhaps the most creative solution to the double-hop issue I have ever seen. Bravo!