---
title: "AD CS Part 1: Architecture, Template Semantics, and the ESC Taxonomy"
description: "Deconstructing the Active Directory Certificate Services attack surface: template attributes, PKINIT credential exchange, EKU semantics, identity mapping, and the ESC taxonomy mapped by root cause."
date: 2026-11-05
author: Sevban Dönmez (@jankesec)
canonical: https://jankesec.com/posts/ad-cs-esc-taxonomy/
---

## The Identity Bridge: How Certificates Become Kerberos Tickets

In Active Directory environments, Active Directory Certificate Services (AD CS) is not merely an auxiliary PKI service for web servers or VPN endpoints. It functions as an authoritative identity provider directly integrated into the Kerberos Key Distribution Center (KDC) via **RFC 4556 (Kerberos PKINIT)**.

Understanding AD CS exploitation requires recognizing one fundamental principle: **an issued X.509 certificate with client authentication capabilities is an unconstrained credential**. When an account acquires a certificate specifying its identity:

1. The client constructs a Kerberos `AS-REQ` containing pre-authentication data of type `16` (`PA-PK-AS-REQ`).
2. The client signs the authentication request with the private key corresponding to the public key in the certificate.
3. The KDC validates the certificate against the `NTAuthCertificates` store in the directory (`CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration,DC=...`).
4. The KDC extracts the principal identity from the Subject Alternative Name (`SAN`) or Object SID extension and issues a Kerberos Ticket Granting Ticket (`TGT`) with an embedded Privilege Attribute Certificate (`PAC`).

This authentication path bypasses password verification, NTLM hash verification, and account password rotation. Whoever controls the certificate enrollment parameters controls the resulting Kerberos ticket.

```
+------------------+         MS-WCCE / RPC          +----------------------+
|  Domain User     | ----------------------------> |  Enterprise CA       |
|  (Enrollee)      | <---------------------------- |  (Issues X.509 Cert) |
+------------------+     Issued Cert (SAN: Target)  +----------------------+
         |
         |  AS-REQ (Pre-Auth Type 16: PA-PK-AS-REQ)
         v
+------------------+                                +----------------------+
|  Kerberos KDC    | =============================> |  Target TGT + PAC    |
|  (Validates PKI) |   Returns TGT for SAN User     |  (Full Impersonation)|
+------------------+                                +----------------------+
```

Every certificate template configuration in Active Directory resolves four core technical questions. Privilege escalation vulnerabilities emerge whenever a template answers one or more of these questions insecurely:

1. **Who can enroll?** Governed by the Discretionary Access Control List (`DACL`) on the template object in LDAP.
2. **Who defines the Subject Alternative Name (SAN)?** Governed by `mspki-certificate-name-flag` (`CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT`) or CA-wide registry flags.
3. **What is the certificate authorized to do?** Governed by Extended Key Usage (`EKU`) OIDs defined in `pKIExtendedKeyUsage`.
4. **How does the KDC map the certificate to a directory account?** Governed by the presence of `szOID_NTDS_CA_SECURITY_EXT` and the KDC registry flag `StrongCertificateBindingEnforcement`.

---

## Enumerating Certificate Authorities and Templates

In the Game of Active Directory (GOAD) multi-forest lab, two distinct Enterprise Certificate Authorities are deployed across the forest boundary. Running `certipy-ad find` against both environments highlights the contrast between a hardened baseline and an exploitable configuration.

### Baseline CA: `SEVENKINGDOMS-CA` (Forest Root)

```bash
$ certipy-ad find -u tywin.lannister@sevenkingdoms.local -p powerkingftw135 -dc-ip 192.168.56.10 -vulnerable -stdout
Certificate Authorities
  0
    CA Name             : SEVENKINGDOMS-CA
    DNS Name            : kingslanding.sevenkingdoms.local
    User Specified SAN  : Disabled
    Enforce Encryption for Requests : Enabled
    Permissions
      Enroll            : SEVENKINGDOMS.LOCAL\Authenticated Users
    [!] Vulnerabilities
      ESC8              : Web Enrollment is enabled over HTTP.
```

The forest root CA enforces encryption, disables user-specified SAN flags, and restricts template modification. The only flagged exposure is `ESC8` (unauthenticated NTLM relay over HTTP web enrollment).

### Exploitable CA: `ESSOS-CA` (Cross-Forest Target)

```bash
$ certipy-ad find -u missandei@essos.local -p fr3edom -dc-ip 192.168.56.12 -vulnerable -stdout
Certificate Authorities
  0
    CA Name             : ESSOS-CA
    DNS Name            : braavos.essos.local
    User Specified SAN  : Enabled        # CA-wide ESC6
    [!] ESC8            : Web Enrollment is enabled over HTTP.
    [!] ESC11           : Encryption is not enforced for ICPR (RPC) requests.

Certificate Templates
  Template Name: ESC1     -> Enrollee supplies subject + Client Authentication EKU
  Template Name: ESC2     -> Any Purpose EKU / No EKU defined
  Template Name: ESC3-CRA -> Certificate Request Agent EKU
  Template Name: ESC4     -> Insecure DACL allows low-priv user GenericWrite
  Template Name: ESC9     -> No Security Extension (Missing Object SID)
  Template Name: WebServer -> Schema version 1 / Server Authentication
```

`ESSOS-CA` answers every fundamental question insecurely. In a production enterprise assessment, templates are rarely named with explicit vulnerability labels like `ESC1`. However, an administrative template named `WebServer_Internal` or `VPN_AutoEnroll` bearing identical bitmask flags presents the exact same attack path.

<figure class="diagram">
<svg viewBox="0 0 760 360" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Active Directory Certificate Services taxonomy: comparing SEVENKINGDOMS-CA and ESSOS-CA, and breaking down the four template configuration questions that govern ESC1 through ESC17 privilege escalation vulnerabilities.">
<text x="12" y="18" class="dg-muted">AD CS ATTACK TAXONOMY · CA CONFIGURATION &amp; TEMPLATE ATTACK PILLARS</text>
<rect x="12" y="28" width="736" height="114" rx="8" class="dg-box-accent" />
<text x="22" y="44" class="dg-accent dg-compact">TWO ENTERPRISE CERTIFICATE AUTHORITIES IN GOAD</text>
<rect x="22" y="52" width="344" height="78" rx="6" class="dg-box" />
<text x="32" y="70" class="dg-label">SEVENKINGDOMS-CA · kingslanding</text>
<text x="32" y="86" class="dg-mono dg-compact">DC01 (192.168.56.10) · Forest Root CA</text>
<text x="32" y="100" class="dg-muted dg-compact">User Specified SAN: Disabled · Encryption: Enforced</text>
<text x="32" y="114" class="dg-accent dg-compact">Hardened Baseline · Only ESC8 (HTTP Web Enrollment)</text>
<rect x="378" y="52" width="360" height="78" rx="6" class="dg-box-danger" />
<text x="388" y="70" class="dg-label">ESSOS-CA · braavos</text>
<text x="388" y="86" class="dg-mono dg-compact">SRV03 (192.168.56.23) · Cross-Forest CA</text>
<text x="388" y="100" class="dg-crit dg-compact" font-weight="700">User Specified SAN: Enabled (EDITF_ATTRIBUTESUBJECTALTNAME2)</text>
<text x="388" y="114" class="dg-crit dg-compact">Vulnerable Templates: ESC1, ESC2, ESC3, ESC6, ESC8, ESC9, ESC11</text>
<rect x="12" y="152" width="736" height="170" rx="8" class="dg-box" />
<text x="22" y="168" class="dg-muted dg-compact">THE 4 CORE QUESTIONS · A VULNERABILITY IS ONE QUESTION ANSWERED WRONG</text>
<rect x="22" y="176" width="172" height="136" rx="6" class="dg-box" />
<text x="32" y="194" class="dg-accent dg-compact">[PILLAR 1 · ACCESS]</text>
<text x="32" y="212" class="dg-label">1 · Who Enrolls?</text>
<text x="32" y="228" class="dg-mono dg-compact">Enroll / AutoEnroll ACE</text>
<text x="32" y="244" class="dg-muted dg-compact">Domain Users = Everyone</text>
<text x="32" y="260" class="dg-muted dg-compact">The Universal Precondition</text>
<text x="32" y="278" class="dg-mono dg-compact">Certipy: Enrollment Rights</text>
<text x="32" y="294" class="dg-accent dg-compact">Amplifier for all ESCs</text>
<rect x="204" y="176" width="172" height="136" rx="6" class="dg-box-accent" />
<text x="214" y="194" class="dg-crit dg-compact" font-weight="700">[PILLAR 2 · SUBJECT]</text>
<text x="214" y="212" class="dg-label">2 · Who Sets SAN?</text>
<text x="214" y="228" class="dg-mono dg-compact">EnrolleeSuppliesSubject</text>
<text x="214" y="244" class="dg-muted dg-compact">mspki-certificate-name-flag</text>
<text x="214" y="260" class="dg-crit dg-compact">Arbitrary UPN / SAN spoof</text>
<text x="214" y="278" class="dg-crit dg-compact" font-weight="700">ESC1 (Template Flag)</text>
<text x="214" y="294" class="dg-crit dg-compact" font-weight="700">ESC6 (CA-Wide Flag)</text>
<rect x="386" y="176" width="172" height="136" rx="6" class="dg-box-accent" />
<text x="396" y="194" class="dg-accent dg-compact">[PILLAR 3 · PURPOSE]</text>
<text x="396" y="212" class="dg-label">3 · Extended Usage?</text>
<text x="396" y="228" class="dg-mono dg-compact">EnhancedKeyUsage (EKU)</text>
<text x="396" y="244" class="dg-muted dg-compact">Client Authentication</text>
<text x="396" y="260" class="dg-muted dg-compact">Allows Kerberos PKINIT</text>
<text x="396" y="278" class="dg-accent dg-compact">ESC2: Any Purpose EKU</text>
<text x="396" y="294" class="dg-accent dg-compact">ESC3: Certificate Agent</text>
<rect x="568" y="176" width="170" height="136" rx="6" class="dg-box-danger" />
<text x="578" y="194" class="dg-crit dg-compact" font-weight="700">[PILLAR 4 · MAPPING]</text>
<text x="578" y="212" class="dg-label">4 · Maps to Whom?</text>
<text x="578" y="228" class="dg-mono dg-compact">szOID_NTDS_CA_SECURITY_EXT</text>
<text x="578" y="244" class="dg-muted dg-compact">ObjectSID / Strong Binding</text>
<text x="578" y="260" class="dg-crit dg-compact">No SID ext = Weak Mapping</text>
<text x="578" y="278" class="dg-crit dg-compact">ESC9: No security ext</text>
<text x="578" y="294" class="dg-crit dg-compact">ESC10: Weak UPN binding</text>
<rect x="12" y="330" width="736" height="20" rx="4" class="dg-box" style="fill: #0a0c0d; stroke: rgba(255,255,255,0.12);" />
<text x="380" y="344" text-anchor="middle" class="dg-muted dg-compact">RULE: Enroll Right + Enrollee Subject + Client Auth EKU + Weak/No Mapping = Direct TGT via PKINIT</text>
</svg>
<figcaption>Comparative architecture of the two GOAD Certificate Authorities and the four functional questions governing AD CS privilege escalation vectors.</figcaption>
</figure>

---

## The ESC Taxonomy by Architectural Root Cause

Rather than viewing the SpecterOps Certified Pre-Owned taxonomy as an arbitrary list of numbered vulnerabilities, security practitioners should group ESC vectors by their technical failure domain:

| Vector | Technical Root Cause | Precondition / Key Attribute | Applicable EKU OID | Exploitation Impact |
| :--- | :--- | :--- | :--- | :--- |
| **ESC1** | Enrollee supplies arbitrary SAN | `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT` (`0x00010000`) | Client Auth (`1.3.6.1.5.5.7.3.2`) | Direct impersonation of any Tier-0 domain principal |
| **ESC2** | Overly permissive EKU scope | `pKIExtendedKeyUsage` contains All Purpose or empty | Any Purpose (`2.5.29.37.0`) | Client authentication or subordinate CA minting |
| **ESC3** | Enrollment agent delegation abuse | `Certificate Request Agent` EKU present | CRA (`1.3.6.1.4.1.311.20.2.1`) | Enrolls on behalf of other users without managerial approval |
| **ESC4** | Insecure template object ACL | Low-privilege principal has `GenericAll` / `WriteDacl` | Template object in Configuration | Overwrites template flags to weaponize into ESC1 on demand |
| **ESC5** | Insecure PKI container / object ACL | Principal holds `WriteOwner` over CA AD container | `CN=Public Key Services` container | Full compromise of all forest certificate infrastructure |
| **ESC6** | CA-wide SAN injection flag | Registry `EDITF_ATTRIBUTESUBJECTALTNAME2` enabled | Any template with Client Auth EKU | CA-wide arbitrary identity spoofing across all templates |
| **ESC7** | Insecure CA service permissions | Principal holds `ManageCA` or `ManageCertificates` | CA RPC interface / registry | Issues failed requests or mints rogue CA certificates |
| **ESC8** | Unauthenticated HTTP enrollment relay | AD CS Web Enrollment active without EPA / HTTPS | NTLM authentication to `/certsrv/` | Coerced NTLM relay from domain computers to obtain machine certs |
| **ESC9** | Absence of security extension | `CT_FLAG_NO_SECURITY_EXTENSION` (`0x00080000`) | Client Auth with UPN fallback | Shadow account hijacking via `GenericWrite` on UPN |
| **ESC10** | Registry-level weak binding fallback | `StrongCertificateBindingEnforcement < 2` on KDC | Client Auth without SID verification | UPN fallback collision bypasses certificate-to-account verification |
| **ESC11** | Unencrypted ICPR RPC interface | CA does not enforce `IF_ENCRYPTED` flag | RPC interface over port 135 / dynamic | Relays unencrypted RPC certificate enrollment |
| **ESC15** | Legacy V1 schema EKU mishandling | Schema version 1 template with non-standard flags | CVE-2024-49019 family | Bypasses intended EKU constraints on unpatched Domain Controllers |
| **ESC17** | Server authentication pivot to S4U | Enrollee sets SAN with Server Authentication EKU | Server Auth (`1.3.6.1.5.5.7.3.1`) | Obtains machine identity certificate for S4U2Self delegation abuse |

---

## Detailed Root Cause Analysis

### 1. Subject Alternative Name Specification (ESC1 and ESC6)

The `Subject Alternative Name` (`SAN`) extension defines the principal identity tied to an X.509 certificate. Normal enrollment procedures require the CA to generate the SAN automatically based on the caller's Active Directory account properties (e.g., pulling the user's `userPrincipalName` or `sAMAccountName`).

When `mspki-certificate-name-flag` contains the bit `0x00010000` (`CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT`), the CA allows the certificate requester to inject an arbitrary SAN value during the Certificate Signing Request (CSR):

```bash
# CSR Attribute indicating arbitrary SAN supply:
szOID_SUBJECT_ALT_NAME2 (2.5.29.17) = UPN: daenerys.targaryen@essos.local
```

If the template simultaneously specifies the `Client Authentication` EKU (`1.3.6.1.5.5.7.3.2`) or `Smart Card Logon` (`1.3.6.1.4.1.311.20.2.2`), this configuration constitutes **ESC1**. A low-privileged domain user requests a certificate specifying a Domain Admin's UPN, authenticates through PKINIT, and receives the privileged account's TGT.

**ESC6** shifts this vulnerability from the individual template to the Certificate Authority service itself. By setting the CA registry flag `EDITF_ATTRIBUTESUBJECTALTNAME2` (`0x00040000`), administrators enable client-specified SAN attributes across *every* template published by that CA. Even templates explicitly configured with `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT = False` become vulnerable if they support client authentication.

### 2. Extended Key Usage Semantics (ESC2, ESC3, and ESC17)

The `pKIExtendedKeyUsage` attribute restricts how a generated certificate can be used by client applications:

```bash
Client Authentication      : 1.3.6.1.5.5.7.3.2
Smart Card Logon           : 1.3.6.1.4.1.311.20.2.2
Any Purpose (All Purpose)  : 2.5.29.37.0
Certificate Request Agent  : 1.3.6.1.4.1.311.20.2.1
Server Authentication      : 1.3.6.1.5.5.7.3.1
```

- **ESC2 (Any Purpose EKU):** If a template includes the `Any Purpose` OID (`2.5.29.37.0`) or omits the EKU extension entirely, the certificate acts as a universal credential. It can be used for client authentication or to sign secondary certificate requests.
- **ESC3 (Certificate Request Agent):** Templates configured with the `Certificate Request Agent` EKU permit the enrollee to act as an enrollment proxy. An attacker requests an Enrollment Agent certificate, then uses it to co-sign an enrollment request on behalf of a target privileged user against a secondary template, bypassing standard authentication checks.
- **ESC17 (Server Authentication Pivot):** While defenders frequently audit templates for Client Authentication, templates with Server Authentication (`1.3.6.1.5.5.7.3.1`) that allow user-specified subjects permit an attacker to request certificates on behalf of computer accounts. The resulting machine certificate enables Kerberos Constrained Delegation (S4U2Self / S4U2Proxy) attacks.

### 3. Identity Binding and Security Extensions (ESC9 and ESC10)

For the KDC to process PKINIT, it must map the certificate to a directory account. In legacy environments, the KDC simply parsed the UPN from the certificate's SAN and matched it to an account's `userPrincipalName` attribute in LDAP.

To prevent UPN spoofing and account collision attacks (such as CVE-2022-26923), Microsoft introduced the Object SID security extension:

```bash
szOID_NTDS_CA_SECURITY_EXT (1.3.6.1.4.1.311.25.2) = ASN.1 Encoded Object SID
```

When this extension is present, the KDC verifies that the certificate's embedded SID matches the authenticating account's `objectSid`.

- **ESC9:** The template specifies `mspki-enrollment-flag` containing `0x00080000` (`CT_FLAG_NO_SECURITY_EXTENSION`). The issued certificate carries no SID extension. If an attacker possesses `GenericWrite` permissions over a victim account's `userPrincipalName`, they change the victim's UPN to a temporary value, enroll a certificate under their own account using the victim's UPN, revert the changes, and authenticate as the victim.
- **ESC10:** Governed by the Domain Controller registry key `HKLM\System\CurrentControlSet\Services\Kdc\StrongCertificateBindingEnforcement`. If this value is set to `0` (Disabled) or `1` (Compatibility Mode), the KDC accepts certificates lacking the SID extension without performing strong binding checks. Only setting `StrongCertificateBindingEnforcement = 2` enforces strict mapping and neutralizes ESC9 fallback.

### 4. PKI Object Access Control (ESC4, ESC5, and ESC7)

In Active Directory, certificate templates and Certificate Authority definitions are stored as standard LDAP objects under the `Configuration` naming context:

```bash
Templates : CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
CA Object : CN=ESSOS-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
```

Every standard object DACL rule applies:

- **ESC4:** A low-privileged account holds `WriteProperty`, `WriteDacl`, or `GenericAll` over a certificate template object. The attacker modifies `mspki-certificate-name-flag` to enable `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT`, adds `Domain Users` to the template's `Enroll` ACE, and converts a non-privileged template into an active ESC1 vector.
- **ESC7:** An account holds `ManageCA` or `ManageCertificates` on the Certificate Authority object. `ManageCertificates` allows approving pending certificate requests that require managerial sign-off. `ManageCA` allows modifying CA configuration parameters via RPC, including enabling `EDITF_ATTRIBUTESUBJECTALTNAME2` or publishing subordinate CA certificates.

---

## Defensive Engineering and Detection Telemetry

Auditing and defending Active Directory Certificate Services requires monitoring both certificate lifecycle events on the CA and authentication traffic on Domain Controllers.

### Critical Event IDs for AD CS Monitoring

| Event Source | Event ID | Channel | Detection Signal |
| :--- | :--- | :--- | :--- |
| **Active Directory CS** | `4886` | Security | Certificate request submitted (audits requester, template name, and requested SAN). |
| **Active Directory CS** | `4887` | Security | Certificate issued by CA (audits issued UPN/SAN and template). |
| **Active Directory CS** | `4898` | Security | Certificate template loaded or modified (indicates potential ESC4 tampering). |
| **Kerberos KDC** | `4768` | Security | TGT requested via PKINIT: `Pre-Authentication Type = 16` (`PA-PK-AS-REQ`). |
| **Directory Service** | `5136` | Security | Directory object modified: captures writes to `mspki-certificate-name-flag` or template DACL. |

```kql
// KQL Query: Detect PKINIT TGT Requests by Non-Standard Accounts
SecurityEvent
| where EventID == 4768
| extend PreAuthType = tostring(parse_xml(EventData).Data[4].["#text"])
| where PreAuthType == "16"
| extend TargetAccount = tostring(parse_xml(EventData).Data[0].["#text"])
| project TimeGenerated, Computer, TargetAccount, IpAddress, PreAuthType
```

### Remediation Protocol

1. **Eliminate Enrollee-Supplied Subjects:** Audit all published templates using `certipy-ad find -vulnerable`. Remove `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT` (`0x00010000`) from any template accessible by non-administrative principals.
2. **Disable CA-Wide SAN Injection:** Execute on all Enterprise CAs:
   ```cmd
   certutil -config "braavos.essos.local\ESSOS-CA" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
   net stop certsvc && net start certsvc
   ```
3. **Enforce Strong Certificate Binding:** On all Domain Controllers, set:
   ```cmd
   reg add "HKLM\SYSTEM\CurrentControlSet\Services\Kdc" /v StrongCertificateBindingEnforcement /t REG_DWORD /d 2 /f
   ```
4. **Harden Template Access Control:** Ensure non-administrative users do not hold `GenericWrite`, `WriteDacl`, or `WriteProperty` rights over objects in `CN=Certificate Templates`.
5. **Disable Plaintext Web Enrollment:** Remove the `CertSrv` virtual directory from IIS or enforce HTTPS with Extended Protection for Authentication (EPA).

---

## Up Next in Part 2

With the architectural foundation established, [Part 2: ESC1 Exploitation](/posts/ad-cs-esc1-domain-admin/) demonstrates the live weaponization of `ESC1` against `ESSOS-CA`. We examine RPC endpoint targeting, analyze the PKINIT authentication exchange, and execute a DRSUAPI DCSync to extract forest root credentials.

---

## Evidence and limits

Certificate Authority and template enumerations were run against `SEVENKINGDOMS-CA` (`192.168.56.10`) and `ESSOS-CA` (`192.168.56.23`) inside the isolated GOAD lab. All template attributes, OIDs, and DACLs reflect GOAD's intentionally vulnerable PKI configuration.

## References

- **Orange Cyberdefense, GOAD:** [orange-cyberdefense.github.io/GOAD](https://orange-cyberdefense.github.io/GOAD/)
- **SpecterOps, Certified Pre-Owned:** [posts.specterops.io](https://posts.specterops.io/certified-pre-owned-d95910965cd2)
- **The Hacker Recipes, Active Directory Certificate Services:** [thehacker.recipes/ad/movement/adcs](https://www.thehacker.recipes/ad/movement/adcs)
- **Microsoft, AD CS Architecture and Protocol Overview:** [learn.microsoft.com](https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/active-directory-certificate-services-overview)
- **Microsoft, KB5014754: Certificate-based authentication changes:** [support.microsoft.com](https://support.microsoft.com/help/5014754)
- **MITRE ATT&CK, Steal or Forge Authentication Certificates (T1649):** [attack.mitre.org/techniques/T1649](https://attack.mitre.org/techniques/T1649/)