The "second hop problem" refers to a situation like the following:
There are several ways to address this problem. The following table lists the methods in order of preference.
Configuration Note CredSSP Balances ease of use and security Resource-based Kerberos constrained delegation Higher security with simpler configuration Kerberos constrained delegation High security but requires Domain Administrator Kerberos delegation (unconstrained) Not recommended Just Enough Administration (JEA) Can provide the best security but requires more detailed configuration PSSessionConfiguration using RunAs Simpler to configure but requires credential management Pass credentials inside anInvoke-Command
script block Simplest to use but you must provide credentials 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 Enable PowerShell "Second-Hop" Functionality with CredSSP.
ProsYou can use legacy constrained delegation (not resource-based) to make the second hop. Configure Kerberos constrained delegation with the option "Use any authentication protocol" to allow protocol transition.
ProsUsing 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 accepts delegated credentials.
ProsLet'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 supported versions of Windows Server, and that there is at least one Windows domain controller for each trusted domain.
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:
Add-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
Get-Command -ParameterName PrincipalsAllowedToDelegateToAccount
Several available cmdlets now have a PrincipalsAllowedToDelegateToAccount parameter:
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 ServerA).
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:
Get-CimInstance Win32_Service -Filter 'Name="winrm"' | Select-Object StartName
StartName
---------
NT AUTHORITY\NetworkService
For ServerC to allow delegation from a PowerShell remoting session on ServerB, we must set 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 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:
scope modifier is used to make the $ServerC
variable visible to ServerB. For more information about the Using:
scope modifier, 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
$servers = @(
$ServerB1,
$ServerB2,
$ServerB3
)
# Grant resource-based Kerberos constrained delegation
Set-ADComputer -Identity $ServerC -PrincipalsAllowedToDelegateToAccount $servers
If you want to make the second hop across domains, use the Server parameter to specify 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
You can also use Kerberos unconstrained delegation to make the second hop. Like all Kerberos scenarios, credentials aren't stored. This method doesn't support the second hop for WinRM.
Warning
This method provides no control of where delegated credentials are used. It's less secure than CredSSP. This method should only be used for testing scenarios.
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.
ProsYou 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.
ProsYou can pass credentials inside the ScriptBlock parameter of a call to the Invoke-Command cmdlet.
ProsThe following example shows how to pass credentials in a 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
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4