Kerbrute
Kerbrute is a Go tool by Ronnie Flathers (@ropnop) for
interacting with the Kerberos authentication service of an Active
Directory KDC from a Linux (or Windows) attack host. Its four commands cover the
credential-access kill chain against AD: userenum (username enumeration),
passwordspray (one password, many users), bruteuser (many passwords, one user),
and bruteforce (username:password combos). It speaks raw Kerberos rather than LDAP
or SMB, which makes it fast and hard to distinguish from normal pre-authentication
traffic at the network layer.
- Repo: github.com/ropnop/kerbrute
- MITRE: T1087.002 — Account Discovery: Domain Account, T1110.003 — Password Spraying
How user enumeration works
kerbrute userenum sends an AS-REQ without pre-authentication data to the KDC
(UDP or TCP port 88) for each candidate username and reads the error code in the
KDC’s reply:
| KDC reply | Meaning |
|---|---|
KDC_ERR_PREAUTH_REQUIRED | User exists — the KDC demands an encrypted timestamp |
KDC_ERR_C_PRINCIPAL_UNKNOWN | User does not exist |
KDC_ERR_PREAUTH_FAILED | (during spraying) valid user, wrong password |
The transaction is never completed — no login failure is generated for userenum,
so it does not trip lockouts or failed-logon auditing by itself. It does, however,
generate an AS-REQ per guess, and passwordspray/bruteuser will lock accounts
out (each attempt is a real pre-auth failure); the --safe flag aborts on the first
lockout, and --delay forces single-threaded throttled guesses.
# Enumerate valid domain users from a wordlist
kerbrute userenum -d $TARGET_DOMAIN usernames.txt
# Target a specific KDC by IP when DNS is unavailable
kerbrute userenum --dc $DC_IP -d $TARGET_DOMAIN usernames.txt -o valid-users.txt
# Password spray one password against the enumerated users
kerbrute passwordspray -d $TARGET_DOMAIN valid-users.txt 'Welcome1'Requirements are minimal: reachability to a KDC. Either be on a network where the
domain’s DNS resolves the KDC automatically, or pass --dc $DC_IP (the DC normally
hosts the KDC) / map the domain in /etc/hosts.
The wire format — and a free AS-REP roast
The packet Kerbrute sends is the start of a standard AS exchange. Watching the
conversation in Wireshark reveals a useful side effect: when an account has
“Do not require Kerberos preauthentication” set, the KDC replies with a full
AS-REP — a ticket encrypted with the user’s NT hash — rather than the usual
PREAUTH_REQUIRED error. That AS-REP is exactly the artifact as-rep-roasting
cracks offline, so a Kerbrute-style sweep doubles as unauthenticated discovery of
pre-auth-disabled accounts (the same thing impacket’s GetNPUsers.py -no-pass
does deliberately). Extracted hashes feed straight into john-the-ripper or
Hashcat (-m 18200, $krb5asrep$23$...).
Related: kerberos, as-rep-roasting, kerberoasting, impacket.
Detection & defense
- Event 4768 (TGT requested) spikes from a single source IP — especially bursts of pre-auth type 0, or 4768s for accounts that never log in — are the canary for both userenum and spraying.
- A honey account with pre-auth deliberately disabled yields near-zero-false-positive AS-REP-roast alerts.
- Enforce pre-authentication on all accounts (audit
DONT_REQUIRE_PREAUTH/ userAccountControl bit 4194304), and set lockout policy so sprays self-limit — accepting that this trades availability for detection.