Renaming the nomenclature: ESC1a, ESC1b, EAB1, and EAB2

At DEFCON 34 we presented five privilege escalation techniques in Active Directory Certificate Services, originally numbered ESC18 through ESC22. After the conference, and after discussing it with Oliver Lyak (the author of Certipy), we did two things: we renamed the techniques so their nomenclature reflects the family they belong to, and we dropped one of them — the original ESC19 — because it does not stand on its own. The result is four techniques: ESC1a, ESC1b, EAB1, and EAB2. This post explains the mapping and the reasoning.

Why the nomenclature changed

Our initial classification gave each technique a sequential ESC number. After deeper analysis, and following a conversation with Oliver Lyak, it became clear that a sequential number implies a standalone attack class, which is not accurate here: every one of these techniques is a variant of, or a specific mechanism within, an escalation family that already exists. The numbering was technically correct but architecturally misleading, and we preferred to fix that rather than leave tooling and reports pointing at the wrong abstraction.

The criterion we adopted, which matches how tools like Certipy evaluate templates, is to name the techniques by the template condition that enables them, not by the final escalation outcome. This has a practical benefit: a single vulnerable template (for example, ESS + no EKU) produces coherent, grouped findings instead of overlapping with several different ESC numbers that would only muddy the analysis.

Under that criterion:

  • The techniques that live on ESS templates and abuse the CA deferring to the CSR belong to the ESC1 family. They share the same root prerequisite (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) and attack surface, and differ only in how they manipulate the certificate’s extensions — a Certificate Policies injection for ESC1a, a Security Extension omission for ESC1b. That is why they become ESC1a and ESC1b.
  • The techniques based on abusing enrollment delegation (Enroll On Behalf Of) form their own family, since they don’t rely on ESS but on the absence of enrollment-agent validation. That is why they get the EAB (Enrollment Agent Bypass) label: EAB1 and EAB2.

Old numbering to new names

  • ESC18 → ESC1a — Certificate Policies passthrough and AMA escalation.
  • ESC19 → removed — SID injection via Security Extension passthrough (reasoning below).
  • ESC20 → ESC1b — Security Extension omission and SAN URL SID fallback.
  • ESC21 → EAB1 — V1 EOBO bypass, missing RA-signature enforcement.
  • ESC22 → EAB2 — unrestricted EOBO with no Enrollment Agent Restrictions.

Why we removed ESC19

The original ESC19 was SID injection via the Security Extension: on an ESS template the attacker supplies the Security Extension (szOID_NTDS_CA_SECURITY_EXT, OID 1.3.6.1.4.1.311.25.2) carrying a target SID in the CSR, the CA copies it into the issued certificate, and at PKINIT the KDC performs strong mapping against that attacker-controlled SID. This is the -sid primitive already exposed by Certipy and Certify.

Elad Shamir questioned what was actually new about it, and after re-reading the Certipy wiki ESC1 section and SpecterOps’ Certify ESC1 documentation we agreed with him: nothing. Supplying the target SID for strong mapping via -sid, and the no-EKU / Subordinate CA case, are both already documented as part of ESC1, and have worked that way since 2023. A separate ESC designation was not warranted on that basis, so ESC19 folds into ESC1 rather than becoming its own technique.

What neither reference states is the mechanism that lets -sid defeat Full Enforcement. Strong mapping resolves identity from the Security Extension, and for a requester-supplied value to survive into the issued certificate the OID 1.3.6.1.4.1.311.25.2 has to be present in the CA’s EnableEnrolleeRequestExtensionList. If it is not, the CA generates the extension itself with the enrollee’s real SID and the spoof fails at StrongCertificateBindingEnforcement = 2. This is a CA-level precondition, governed by EnableEnrolleeRequestExtensionList independently of CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT — a property of the CA, not of the template, which is another reason it does not define a technique of its own. We document it here because it is the piece the existing ESC1 references leave implicit.

Technique summary

  • ESC1a: Certificate Policies (OID 2.5.29.32) passthrough via CSR extension injection. Self-escalation through Authentication Mechanism Assurance (AMA).
  • ESC1b: Security Extension omission on an ESS template, forcing the KDC to fall back to the attacker-controlled SAN URL SID. Identity spoofing; bypasses SCBE at all levels.
  • EAB1: EOBO bypass on V1 templates due to missing msPKI-RA-Signature enforcement.
  • EAB2: Unrestricted EOBO when no Enrollment Agent Restrictions are configured on the CA.

All of the techniques are exploitable from an unprivileged domain user account and are independent of StrongCertificateBindingEnforcement (SCBE) at every level.

ESC1a and ESC1b in detail

ESC1a. On an ESS template (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) the enrollee controls the subject, and when the CA also honours enrollee-supplied request extensions the attacker injects a Certificate Policies extension (OID 2.5.29.32) carrying an issuance-policy OID. If that issuance policy is linked to a privileged group through Authentication Mechanism Assurance (OID-to-group links), the issued certificate grants that group membership at authentication time. The escalation comes from the injected policy, not from changing the subject’s identity.

ESC1b. The same ESS template, but instead of injecting an extension the attacker omits the Security Extension (szOID_NTDS_CA_SECURITY_EXT, OID 1.3.6.1.4.1.311.25.2) from the CSR. On an ESS template the CA defers to the request and does not add the extension on its own, so the certificate is issued without it. During PKINIT the KDC, finding no Security Extension, falls back to the SID encoded in the SAN URL field (tag:microsoft.com,2022-09-14:sid:<SID>), which the attacker also controls through ESS. The result is identity spoofing as the target principal. This KDC fallback is undocumented and is not blocked by SCBE = 2.

Acknowledgements

  • To Oliver Lyak (ly4k), author of Certipy, for the conversation that led to this renaming and for his work on the tool.
  • To Elad Shamir for questioning the novelty of the original ESC19 against ESC1, which led us to fold it in and to document the EnableEnrolleeRequestExtensionList mechanism behind -sid at Full Enforcement.
  • To DEFCON for letting us present this research at the conference.
  • To all the attendees for the feedback received during and after the talk.

Tooling

A fork of Certipy with support for these techniques is available at github.com/e1abrador/Certipy.

Paper

The full paper is available at: defcon-34-paper.pdf