Making the second hop in PowerShell Remoting

The "second hop problem" refers to a situation like the following:

  1. You are logged in to ServerA.
  2. From ServerA, you start a remote PowerShell session to connect to ServerB.
  3. A command you run on ServerB via your PowerShell Remoting session attempts to access a resource on ServerC.
  4. Access to the resource on ServerC is denied, because the credentials you used to create the PowerShell Remoting session are not passed from ServerB to ServerC.

There are several ways to address this problem. In this topic, we'll look at several of the most popular solutions to the second hop problem.

CredSSP

You can use the Credential Security Support Provider (CredSSP) for authentication. CredSSP caches credentials on the remote server (ServerB), so using it opens you up to credential theft attacks. If the remote computer is compromised, the attacker has access to the user's credentials. CredSSP is disabled by default on both client and server computers. You should enable CredSSP only in the most trusted environments. For example, a domain administrator connecting to a domain controller because the domain controller is highly trusted.

For more information about security concerns when using CredSSP for PowerShell Remoting, see Accidental Sabotage: Beware of CredSSP.

For more information about credential theft attacks, see Mitigating Pass-the-Hash (PtH) Attacks and Other Credential Theft.

For an example of how to enable and use CredSSP for PowerShell remoting, see Using CredSSP to solve the second-hop problem.

Pros

  • It works for all servers with Windows Server 2008 or later.

Cons

  • Has security vulnerabilities.
  • Requires configuration of both client and server roles.

Kerberos delegation (unconstrained)

You can also used Kerberos unconstrained delegation to make the second hop. However, this method provides no control of where delegated credentials are used.

Note: Active Directory accounts that have the Account is sensitive and cannot be delegated property set cannot be delegated. For more information, see Security Focus: Analysing 'Account is sensitive and cannot be delegated' for Privileged Accounts and Kerberos Authentication Tools and Settings

Pros

  • Requires no special coding.

Cons

  • Does not support the second hop for WinRM.
  • Provides no control over where credentials are used, creating a security vulnerability.

Kerberos constrained delegation

You can use legacy constrained delegation (not resource-based) to make the second hop.

Note: Active Directory accounts that have the Account is sensitive and cannot be delegated property set cannot be delegated. For more information, see Security Focus: Analysing 'Account is sensitive and cannot be delegated' for Privileged Accounts and Kerberos Authentication Tools and Settings

Pros

  • Requires no special coding

Cons

  • Does not support the second hop for WinRM.
  • Must be configured on the Active Directory object of the remote server (ServerB).
  • Limited to one domain. Cannot cross domains or forests.
  • Requires rights to update objects and Service Principal Names (SPNs).

Resource-based Kerberos constrained delegation

Using resource-based Kerberos constrained delegation (introduced in Windows Server 2012), you configure credential delegation on the server object where resources reside. In the second hop scenario described above, you configure ServerC to specify from where it will accept delegated credentials.

Note: Active Directory accounts that have the Account is sensitive and cannot be delegated property set cannot be delegated. For more information, see Security Focus: Analysing 'Account is sensitive and cannot be delegated' for Privileged Accounts and Kerberos Authentication Tools and Settings

Pros

  • Credentials are not stored.
  • Relatively easy to configure by using PowerShell cmdlets--no special coding required.
  • No special domain access is required.
  • Works across domains and forests.
  • PowerShell code.

Cons

  • Requires Windows Server 2012 or later.
  • Does not support the second hop for WinRM.
  • Requires rights to update objects and Service Principal Names (SPNs).

Example

Let's look at a PowerShell example that configures resource based constrained delegation on ServerC to allow delegated credentials from a ServerB. This example assumes that all servers are running Windows Server 2012 or later, and that there is at least one Windows Server 2012 domain controller each domain to which any of the servers belong.

Before you can configure constrained delegation, you must add the RSAT-AD-PowerShell feature to install the Active Directory PowerShell module, and then import that module into your session:

PS C:\> Add-WindowsFeature RSAT-AD-PowerShell

PS C:\> Import-Module ActiveDirector

Several available cmdlets now have a PrincipalsAllowedToDelegateToAccount parameter:

PS C:\> Get-Command -ParameterName PrincipalsAllowedToDelegateToAccount

CommandType Name                 ModuleName     
----------- ----                 ----------     
Cmdlet      New-ADComputer       ActiveDirectory
Cmdlet      New-ADServiceAccount ActiveDirectory
Cmdlet      New-ADUser           ActiveDirectory
Cmdlet      Set-ADComputer       ActiveDirectory
Cmdlet      Set-ADServiceAccount ActiveDirectory
Cmdlet      Set-ADUser           ActiveDirectory

The PrincipalsAllowedToDelegateToAccount parameter sets the Active Directory object attribute msDS-AllowedToActOnBehalfOfOtherIdentity, which contains an access control list (ACL) that specifies which accounts have permission to delegate credentials to the associated account (in our example, it will be the machine account for Server).

Now let's set up the variables we'll use to represent the servers:

# Set up variables for reuse            
$ServerA = $env:COMPUTERNAME            
$ServerB = Get-ADComputer -Identity ServerB            
$ServerC = Get-ADComputer -Identity ServerC            

WinRM (and therefore PowerShell remoting) runs as the computer account by default. You can see this by looking at the StartName property of the winrm service:

PS C:\> Get-WmiObject win32_service -filter 'name="winrm"' | Format-List StartName

StartName : NT AUTHORITY\NetworkService

For ServerC to allow delegation from a PowerShell remoting session on ServerB, we will grant access by setting the PrincipalsAllowedToDelegateToAccount parameter on ServerC to the computer object of ServerB:

# Grant resource-based Kerberos constrained delegation            
Set-ADComputer -Identity $ServerC -PrincipalsAllowedToDelegateToAccount $ServerB            

# Check the value of the attribute directly            
$x = Get-ADComputer -Identity $ServerC -Properties msDS-AllowedToActOnBehalfOfOtherIdentity            
$x.'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access            

# Check the value of the attribute indirectly            
Get-ADComputer -Identity $ServerC -Properties PrincipalsAllowedToDelegateToAccount

The Kerberos Key Distribution Center (KDC) caches denied access attempts (negative cache) for 15 minutes. If ServerB has previously attempted to access ServerC, you will need to clear the cache on ServerB by invoking the following command:

Invoke-Command -ComputerName $ServerB.Name -Credential $cred -ScriptBlock {            
    klist purge -li 0x3e7            
}

You could also restart the computer, or wait at least 15 minutes to clear the cache.

After clearing the cache, you can successfully run code from ServerA through ServerB to ServerC:

# Capture a credential            
$cred = Get-Credential Contoso\Alice            

# Test kerberos double hop            
Invoke-Command -ComputerName $ServerB.Name -Credential $cred -ScriptBlock {            
    Test-Path \\$($using:ServerC.Name)\C$            
    Get-Process lsass -ComputerName $($using:ServerC.Name)            
    Get-EventLog -LogName System -Newest 3 -ComputerName $($using:ServerC.Name)            
}

In this example, the $using variable is used to make the $ServerC variable visible to ServerB. For more information about the $using variable, see about_Remote_Variables.

To allow multiple servers to delegate credentials to ServerC, set the value of the PrincipalsAllowedToDelegateToAccount parameter on ServerC to an array:

# Set up variables for each server            
$ServerB1 = Get-ADComputer -Identity ServerB1            
$ServerB2 = Get-ADComputer -Identity ServerB2            
$ServerB3 = Get-ADComputer -Identity ServerB3            
$ServerC  = Get-ADComputer -Identity ServerC            

# Grant resource-based Kerberos constrained delegation            
Set-ADComputer -Identity $ServerC `
    -PrincipalsAllowedToDelegateToAccount @($ServerB1,$ServerB2,$ServerB3)

If you want to make the second hop across domains, add fully-qualified domain name (FQDN) of the domain controller of the domain to which ServerB belongs:

# For ServerC in Contoso domain and ServerB in other domain            
$ServerB = Get-ADComputer -Identity ServerB -Server dc1.alpineskihouse.com            
$ServerC = Get-ADComputer -Identity ServerC            
Set-ADComputer -Identity $ServerC -PrincipalsAllowedToDelegateToAccount $ServerB

To remove the ability to delegate credentials to ServerC, set the value of the PrincipalsAllowedToDelegateToAccount parameter on ServerC to $null:

Set-ADComputer -Identity $ServerC -PrincipalsAllowedToDelegateToAccount $null

Information on resource-based Kerberos constrained delegation

PSSessionConfiguration using RunAs

You can create a session configuration on ServerB and set its RunAsCredential parameter.

For information about using PSSessionConfiguration and RunAs to solve the second hop problem, see Another solution to multi-hop PowerShell remoting.

Pros

  • Works with any server with WMF 3.0 or later.

Cons

  • Requires configuration of PSSessionConfiguration and RunAs on every intermediate server (ServerB).
  • Requires password maintenance when using a domain RunAs account

Just Enough Administration (JEA)

JEA allows you to restrict what commands an administrator can run during a PowerShell session. It can be used to solve the second hop problem.

For information about JEA, see Just Enough Administration.

Pros

  • No password maintenance when using a virtual account.

Cons

  • Requires WMF 5.0 or later.
  • Requires configuration on every intermediate server (ServerB).

Pass credentials inside an Invoke-Command script block

You can pass credentials inside the ScriptBlock parameter of a call to the Invoke-Command cmdlet.

Pros

  • Does not require special server configuration.
  • Works on any server running WMF 2.0 or later.

Cons

  • Requires an awkward code technique.
  • If running WMF 2.0, requires different syntax for passing arguments to a remote session.

Example

The following example shows how to pass credentials in an Invoke-Command script block:

# This works without delegation, passing fresh creds            
# Note $Using:Cred in nested request            
$cred = Get-Credential Contoso\Administrator            
Invoke-Command -ComputerName ServerB -Credential $cred -ScriptBlock {            
    hostname            
    Invoke-Command -ComputerName ServerC -Credential $Using:cred -ScriptBlock {hostname}            
}

See also

PowerShell Remoting Security Considerations