Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

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-PSSessionConfiguration needs a credential popup — no headless operation
  • Doesn’t work from PowerShell on Linux due to Kerberos credential handling differences

Other Workarounds

MethodDescription
CredSSPDelegates credentials to the remote host; must be enabled on both client and server
Port forwardingForward traffic through the first hop to reach the second resource directly
Sacrificial process injectionInject into a process running as a user whose credentials are cached on the target
Nested Invoke-CommandWrap the second-hop command in an Invoke-Command that passes credentials

Quick Decision Matrix

ScenarioBest Workaround
evil-winrm sessionPSCredential object with -Credential on every command
Enter-PSSession from Windows with GUIRegister PSSession Configuration
RDP sessionNo workaround needed — double hop doesn’t apply
PSExec / SMB authenticationNo workaround needed — NTLM hash is cached