Skip to main content
All articles

Your certificate authority is an authentication system: ESC1, the SID extension, and what changed in 2025

ESC1 turns a low-privileged domain account into a domain admin certificate. Strong certificate mapping was supposed to end that, and since September 2025 it cannot be switched off. Here is what still works, what does not, and how to check your own templates.

8 min read3 views

Most enterprises running Active Directory also run Active Directory Certificate Services, and most of those deployments have never been audited, because the mental model of a CA is "the thing that issues TLS certificates" rather than "an authentication system with its own privilege escalation paths."

That second description is the accurate one. A certificate carrying the Client Authentication extended key usage and a Subject Alternative Name of administrator@corp.local is, to a Kerberos-aware service, a domain administrator. The CA will sign it for whoever asks, correctly, if the template governing the request is misconfigured. Everything about the security of that path lives in template configuration that in most environments nobody has looked at since the day it was set up.

The research that reframed this was SpecterOps' Certified Pre-Owned by Will Schroeder and Lee Christensen, published in 2021. It catalogued eight domain escalation classes, ESC1 through ESC8. The community has since added more, and current tooling enumerates well past the original set.

What makes a template exploitable

ESC1 is the first and most common. Nearly every write-up lists three conditions. There are five, and the two that get dropped are the two that decide whether a template you found is actually exploitable or merely untidy.

  1. The template grants enrollment rights to a principal you control, typically Domain Users or Authenticated Users.
  2. The template sets CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT, letting the requester specify the Subject Alternative Name.
  3. The template carries an EKU that permits client authentication: Client Authentication, Smart Card Logon, PKINIT Client Authentication, or Any Purpose.
  4. Manager approval is disabled. If PEND_ALL_REQUESTS is set, every request sits in a queue until a human approves it, and the attack stops there.
  5. No authorized signatures are required. If the template demands one or more authorised signatures, the requester needs an enrollment agent certificate first, which is a different problem (ESC3).

Auditing on the first three alone produces false positives. A template with enrollee-supplied subject, a client auth EKU and Domain Users enrollment is not exploitable if it also requires manager approval, and plenty of legitimately configured templates look alarming until you check that fourth condition.

When all five hold, any domain user can request a certificate claiming to be any principal in the domain. The CA verifies the requester holds enrollment rights. It does not verify that the SAN they supplied describes them.

# Request a certificate claiming to be the domain administrator
certipy req -u lowpriv@corp.local -p 'Password1' \
    -target ca.corp.local -ca 'corp-CA' \
    -template VulnerableTemplate -upn administrator@corp.local

# Authenticate with it
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1

certipy auth returns a TGT for the target account. No exploit, no payload, no LSASS access. A certificate request and an authentication exchange.

What strong certificate mapping changed

This is the part most ESC1 write-ups have not caught up with, and it is the difference between an article that describes 2022 and one that describes your environment today.

In May 2022, Microsoft shipped KB5014754 in response to certificate spoofing weaknesses. It added a new extension to issued certificates, szOID_NTDS_CA_SECURITY_EXT (OID 1.3.6.1.4.1.311.25.2), carrying the SID of the account the certificate was actually issued to. Domain controllers can then check that the SID in the certificate matches the account being authenticated, rather than trusting the UPN in the SAN.

The behaviour was controlled by a registry value, StrongCertificateBindingEnforcement, with three modes: disabled, compatibility, and full enforcement. For three years most environments sat in compatibility mode, which logs a mismatch and allows the authentication anyway, which is to say ESC1 kept working.

That window is closed. Domain controllers moved to full enforcement by default in February 2025, and since 9 September 2025 the registry value is ignored entirely. There is no compatibility mode and no override.

The practical effect on classic ESC1: a certificate requested by lowpriv with a SAN of administrator@corp.local now carries lowpriv's SID in the security extension. The domain controller compares the two, finds they disagree, and refuses the authentication. The certificate is issued exactly as before. It just does not get you a TGT any more.

Why the templates still matter

If that were the whole story, ESC1 would be a historical note. It is not, for three reasons.

The extension has to be present. Full enforcement requires a strong mapping. A certificate that carries no SID extension at all does not silently pass, but it does push the domain controller onto the explicit mapping stored in altSecurityIdentities, and environments that populated those attributes loosely years ago have a weak binding sitting in the directory waiting to be used. This is the substance of ESC10.

The extension can be suppressed. A template with CT_FLAG_NO_SECURITY_EXTENSION set instructs the CA to omit the SID extension from the certificates it issues. Combined with a writable userPrincipalName on an account you control, that is ESC9, and it exists specifically to defeat the mapping. ESC16 is the same idea applied CA-wide rather than per template.

Everything downstream of authentication is unchanged. ESC4 remains a template ACL problem: write access to a template object lets an attacker reconfigure it into a vulnerable state, use it, and revert. ESC6 is the EDITF_ATTRIBUTESUBJECTALTNAME2 flag on the CA, which permits SAN specification on any request regardless of template settings. ESC8 relays NTLM authentication to the web enrollment interface. None of those were addressed by a change to how certificates map to accounts.

So the honest 2026 position is that strong certificate mapping closed the simplest path and moved the attack one step sideways, into the mapping itself. A template audit is still worth running. It just needs to look for the SID extension suppression flags alongside the classic three.

Testing for it

Certipy needs one valid domain credential and enumerates the whole estate:

certipy find -u lowpriv@corp.local -p 'Password1' -dc-ip 10.0.0.1 -vulnerable -stdout

-vulnerable filters to templates that actually meet the conditions, and -stdout prints straight to the terminal instead of writing a timestamped file you then have to go and find.

BloodHound Community Edition ingests the same template data and surfaces certificate paths in the attack graph alongside standard AD permissions, which is the better view when you want to know whether a path is reachable from a specific starting account rather than whether a template is theoretically weak.

A manual check in certtmpl.msc covers the same ground: the Subject Name tab for "Supply in the request", the Extensions tab for an unnecessary Client Authentication EKU, the Issuance Requirements tab for manager approval and authorised signatures, and the Security tab for who holds Enroll rights.

For the CA-wide flag:

certutil -config "CA-Server\CA-Name" -getreg policy\EditFlags

EDITF_ATTRIBUTESUBJECTALTNAME2 in that output means the CA will accept a requester-supplied SAN on any template.

Fixing it

Remove CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT from every template without a specific documented reason to have it. Smart card provisioning is the usual legitimate case, and it is rarer than the number of templates carrying the flag suggests.

Restrict enrollment to named security groups rather than Authenticated Users or Domain Users. Strip client authentication EKUs from templates that do not need them: code signing and email encryption templates almost never do.

Clear the ESC6 flag if it is set, and restart the service so the change takes:

certutil -config "CA-Server\CA-Name" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
net stop certsvc && net start certsvc

Then audit for CT_FLAG_NO_SECURITY_EXTENSION on every template. Under full enforcement that flag is the thing standing between a misconfigured template and a working escalation, and it has no legitimate use in most environments.

Finally, enable certificate issuance auditing on the CA and forward it. Without it the rest of this is unverifiable.

Detection

Certificate issuance does not reach the Security event log unless issuance auditing has been explicitly enabled at the CA, and it is off by default. The record otherwise lives only in the CA's own database, which most environments never ship anywhere.

With auditing on, event 4887 records an approved request. The signal worth alerting on is a SAN UPN that does not match the requesting account.

On the domain controller side, event 4768 records the TGT request. Certificate-based authentication is rare enough in most environments that any PKINIT authentication deserves a look, and under full enforcement a mapping failure is itself a strong signal that somebody is trying this.

DCSync following an escalation appears as event 4662 carrying DS-Replication-Get-Changes-All, which is the standard indicator regardless of how the attacker arrived.

Take this away

The five conditions matter, not three. Auditing on the short version produces findings that will not reproduce, and the fastest way to lose credibility with an AD team is to hand them a template that turns out to require manager approval.

Strong certificate mapping is not optional any more and has not been since September 2025, which means the classic UPN-spoofing path is closed in any environment running patched domain controllers. The response from the offensive side was not to abandon ADCS, it was to target the mapping: ESC9 and ESC16 suppress the SID extension, ESC10 abuses weak explicit mappings, and template ACL and relay paths were never affected in the first place.

Run Certipy against your own estate on a schedule. Template ACLs drift, new templates appear, and a one-time cleanup does not stay clean. If your last penetration test report contains no Certipy output, that means the CA was out of scope, not that it was clean.


Further reading

Was this useful?

Share

Tags

  • active directory
  • privilege escalation
  • red team
  • detection engineering
  • penetration testing

Comments

Loading comments…

Leave a comment

Comments are read and approved by hand before they appear, so yours will not show up straight away. Your email address is optional, is never published, and is only used if we need to reply to you directly.

0/5000

Related service

Internal & External Penetration Testing

Find the paths into your network, and the paths across it once someone is in.

If you want to know whether what you have just read applies to your own systems, that is the engagement that answers it.