Kerberos “Double Hop” Problem
When authenticating via WinRM/PSRemoting, the user’s credentials are not cached in memory on the remote host. This prevents authentication to a second resource (e.g., querying the DC from a WinRM session). The problem does not occur with RDP or PSExec because those methods store the NTLM hash in memory.
How It Works
Kerberos tickets are resource-specific. When you WinRM to Host A, you receive a TGS ticket for Host A’s HTTP service — but your TGT (Ticket Granting Ticket) is not forwarded to the remote session. Without the TGT, Host A cannot request tickets on your behalf to access Host B (e.g., a Domain Controller).
Attack Host → WinRM → DEV01 (TGS for HTTP/DEV01 — works)
→ LDAP query → DC01 (no TGT — fails)
Why It Doesn’t Happen with RDP/PSExec
- RDP: Password is stored in memory → NTLM hash available for further authentication
- PSExec: Authenticates via SMB → NTLM hash stored in the session
- WinRM: Network authentication → only a TGS ticket for the target service, no cached credentials
Unconstrained Delegation Exception
If unconstrained delegation is enabled on a server, the user’s TGT is sent along with their TGS ticket. The server can then use the cached TGT to request TGS tickets to other services on the user’s behalf, eliminating the double hop problem.
Diagnosing the Problem
Check cached tickets with klist
On a WinRM session, you’ll see only a single TGS ticket for the current host:
klist
# Shows: Server: HTTP/DEV01.DOMAIN.LOCAL (only one ticket, no krbtgt TGT)
On an RDP session to the same host, you’ll see a TGT (krbtgt/DOMAIN) plus TGS tickets for other services — the double hop doesn’t apply.
Mimikatz confirms no credentials cached
Running sekurlsa::logonpasswords on the WinRM target shows no credentials for the WinRM user (processes like wsmprovhost.exe run in the user’s context, but no hash is stored).
Workaround #1: PSCredential Object (evil-winrm / any WinRM session)
Pass credentials explicitly with every command that needs to reach a second hop.
$SecPassword = ConvertTo-SecureString '!qazXSW@' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\backupadm', $SecPassword)
# Now pass -Credential to PowerView commands
Import-Module .\PowerView.ps1
Get-DomainUser -spn -Credential $Cred | select samaccountname
Without -Credential $Cred, the same command fails with “An operations error occurred.” This works from both evil-winrm and Enter-PSSession.
Limitation: Every command that touches a second resource must include -Credential. Some tools don’t support this parameter.
Workaround #2: Register PSSession Configuration (Windows GUI only)
Register a custom session configuration that runs as a specific user. The remote machine impersonates the user for all requests, including to third-party resources.
Step 1: Register the configuration
Register-PSSessionConfiguration -Name backupadmsess -RunAsCredential inlanefreight\backupadm
Step 2: Restart WinRM
Restart-Service WinRM
This disconnects the current session.
Step 3: Reconnect using the named configuration
Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm -ConfigurationName backupadmsess
Step 4: Verify — klist now shows a TGT
klist
# Shows: Server: krbtgt/INLANEFREIGHT.LOCAL (TGT present — double hop solved)
PowerView commands now work without -Credential:
Import-Module .\PowerView.ps1
Get-DomainUser -spn | select samaccountname
Limitations:
- Requires GUI access and an elevated PowerShell console (can’t do this from
evil-winrm) Register-PSSessionConfigurationneeds a credential popup — no headless operation- Doesn’t work from PowerShell on Linux due to Kerberos credential handling differences
Other Workarounds
| Method | Description |
|---|---|
| CredSSP | Delegates credentials to the remote host; must be enabled on both client and server |
| Port forwarding | Forward traffic through the first hop to reach the second resource directly |
| Sacrificial process injection | Inject into a process running as a user whose credentials are cached on the target |
| Nested Invoke-Command | Wrap the second-hop command in an Invoke-Command that passes credentials |
Quick Decision Matrix
| Scenario | Best Workaround |
|---|---|
| evil-winrm session | PSCredential object with -Credential on every command |
| Enter-PSSession from Windows with GUI | Register PSSession Configuration |
| RDP session | No workaround needed — double hop doesn’t apply |
| PSExec / SMB authentication | No workaround needed — NTLM hash is cached |