Kerberos Double Hop Problem

Double Hop Problem with WinRM/Powershell:
Double Hop problem commonly occurs when using WinRM and PowerShell.
Default WinRM authentication provides access only to specific resources, leading to access issues for lateral movement or accessing file shares from a remote shell.
User accounts may have rights to perform actions but are denied access due to authentication limitations.
Shells can be obtained by attacking applications on the target host or using credentials and tools like PSExec.
Initial authentication is often performed over SMB or LDAP, leading to the storage of NTLM Hash in memory.
WinRM is a preferred method for authentication in some cases.
Credential Caching Issue:
The core problem is that WinRM does not cache the user's password when authenticating over multiple connections.
When using Mimikatz to examine the session, all credentials appear blank.
With Kerberos-based remote sessions, password authentication is not used.
In scenarios like PSExec, where password authentication is used, the NTLM hash is stored in the session's memory.
This stored hash allows the machine to authenticate the user when accessing another resource.

When connecting to a remote system like DEV01 using a tool such as evil-winrm, network authentication is used, and user credentials are not stored in memory on the remote system.
The absence of stored credentials means that there are no credentials available to authenticate to other resources on behalf of the user.
When using tools like PowerView to query Active Directory, Kerberos does not recognize the user's ability to access domain resources because the user's Kerberos Ticket Granting Ticket (TGT) is not sent to the remote session.
This absence of the TGT ticket means that the user cannot prove their identity when trying to access resources, resulting in commands no longer running in the user's context.
Specifically, during authentication to the target host, the user's Ticket Granting Service (TGS) ticket is sent to the remote service, enabling command execution. However, the user's TGT ticket is not sent.
When attempting to access additional resources within the domain, the user's TGT is not included in the request, causing the remote service to be unable to validate the authentication attempt. As a result, access to the remote service is denied.
In essence, the absence of the TGT ticket in the remote session prevents the user from proving their identity when accessing domain resources, leading to access denial.
Workarounds
Workaround #1: PSCredential Object
We can also connect to the remote host via host A and set up a PSCredential object to pass our credentials again. Let's see that in action.
After connecting to a remote host with domain credentials, we import PowerView and then try to run a command. As seen below, we get an error because we cannot pass our authentication on to the Domain Controller to query for the SPN accounts.
Let's set up a PSCredential object and try again. First, we set up our authentication.
*Evil-WinRM* PS C:\Users\backupadm\Documents> $SecPassword = ConvertTo-SecureString '!qazXSW@' -AsPlainText -Force
|S-chain|-<>-127.0.0.1:9051-<><>-172.16.8.50:5985-<><>-OK
|S-chain|-<>-127.0.0.1:9051-<><>-172.16.8.50:5985-<><>-OK
*Evil-WinRM* PS C:\Users\backupadm\Documents> $Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\backupadm', $SecPassword)
Now we can try to query the SPN accounts using PowerView and are successful because we passed our credentials along with the command.
*Evil-WinRM* PS C:\Users\backupadm\Documents> get-domainuser -spn -credential $Cred | select samaccountname
|S-chain|-<>-127.0.0.1:9051-<><>-172.16.8.50:5985-<><>-OK
|S-chain|-<>-127.0.0.1:9051-<><>-172.16.8.50:5985-<><>-OK
samaccountname
--------------
azureconnect
backupjob
krbtgt
mssqlsvc
sqltest
sqlqa
sqldev
mssqladm
svc_sql
sqlprod
sapsso
sapvc
vmwarescvc
If we RDP to the same host, open a CMD prompt, and type klist
, we'll see that we have the necessary tickets cached to interact directly with the Domain Controller, and we don't need to worry about the double hop problem. This is because our password is stored in memory, so it can be sent along with every request we make.
C:\htb> klist
Current LogonId is 0:0x1e5b8b
Cached Tickets: (4)
#0> Client: backupadm @ INLANEFREIGHT.LOCAL
Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent name_canonicalize
Start Time: 6/28/2022 9:13:38 (local)
End Time: 6/28/2022 19:13:38 (local)
Renew Time: 7/5/2022 9:13:38 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x2 -> DELEGATION
Kdc Called: DC01.INLANEFREIGHT.LOCAL
#1> Client: backupadm @ INLANEFREIGHT.LOCAL
Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 6/28/2022 9:13:38 (local)
End Time: 6/28/2022 19:13:38 (local)
Renew Time: 7/5/2022 9:13:38 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called: DC01.INLANEFREIGHT.LOCAL
#2> Client: backupadm @ INLANEFREIGHT.LOCAL
Server: ProtectedStorage/DC01.INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
Start Time: 6/28/2022 9:13:38 (local)
End Time: 6/28/2022 19:13:38 (local)
Renew Time: 7/5/2022 9:13:38 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0
Kdc Called: DC01.INLANEFREIGHT.LOCAL
#3> Client: backupadm @ INLANEFREIGHT.LOCAL
Server: cifs/DC01.INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
Start Time: 6/28/2022 9:13:38 (local)
End Time: 6/28/2022 19:13:38 (local)
Renew Time: 7/5/2022 9:13:38 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0
Kdc Called: DC01.INLANEFREIGHT.LOCAL
Workaround #2: Register PSSession Configuration
One trick we can use here is registering a new session configuration using the Register-PSSessionConfiguration cmdlet.
PS C:\htb> Register-PSSessionConfiguration -Name backupadmsess -RunAsCredential inlanefreight\backupadm
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. Verify that the Windows
PowerShell runspace configuration is restricted to only the necessary set of cmdlets and capabilities.
WARNING: Register-PSSessionConfiguration may need to restart the WinRM service if a configuration using this name has
recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be
required.
All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session
configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected.
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin
Type Keys Name
---- ---- ----
Container {Name=backupadmsess} backupadmsess
Once this is done, we need to restart the WinRM service by typing Restart-Service WinRM
in our current PSSession. This will kick us out, so we'll start a new PSSession using the named registered session we set up previously.
After we start the session, we can see that the double hop problem has been eliminated, and if we type klist
, we'll have the cached tickets necessary to reach the Domain Controller. This works because our local machine will now impersonate the remote machine in the context of the backupadm
user and all requests from our local machine will be sent directly to the Domain Controller.
PS C:\htb> Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm -ConfigurationName backupadmsess
[DEV01]: PS C:\Users\backupadm\Documents> klist
Current LogonId is 0:0x2239ba
Cached Tickets: (1)
#0> Client: backupadm @ INLANEFREIGHT.LOCAL
Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 6/28/2022 13:24:37 (local)
End Time: 6/28/2022 23:24:37 (local)
Renew Time: 7/5/2022 13:24:37 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called: DC01
We can now run tools such as PowerView without having to create a new PSCredential object.
[DEV01]: PS C:\Users\Public> get-domainuser -spn | select samaccountname
samaccountname
--------------
azureconnect
backupjob
krbtgt
mssqlsvc
sqltest
sqlqa
sqldev
mssqladm
svc_sql
sqlprod
sapsso
sapvc
vmwarescvc
Last updated