Kerbrute
Fast Active Directory username enumeration and password spraying tool that uses Kerberos pre-authentication. Doesn't trigger traditional logon failure events, making it stealthier than SMB-based attacks.
What is it?
Kerbrute talks directly to the Kerberos service (port 88) on a Domain Controller. It has two main uses:
- User enumeration: Find which usernames are valid in the domain, without needing any credentials
- Password spraying: Try one password against many users via Kerberos
The key advantage: Kerberos pre-authentication requests don't generate the same Windows event logs as NTLM/SMB authentication failures. A failed Kerberos pre-auth generates Event ID 4771 (not the more commonly monitored 4625), and only if auditing is configured for it.
When you send a Kerberos AS-REQ for a valid username with the wrong password, the DC responds with KDC_ERR_PREAUTH_REQUIRED. For an invalid username, it responds with KDC_ERR_C_PRINCIPAL_UNKNOWN. Different error = you can tell valid from invalid usernames without a single successful login.
Run this first
Kerbrute checks each username against Kerberos pre-authentication, which does not log a normal failed-logon event.
$ kerbrute userenum --dc DC01.corp.local -d corp.local users.txt
--dcis the domain controller.-dneeds the full domain name (corp.local), not the NetBIOS name (CORP).
Valid usernames print as found. Feed that list into password spraying, one password at a time, with a wait between attempts so you do not lock accounts out.
When do you use it?
- You found a DC (port 88 open) but have no credentials at all → enumerate valid usernames
- You found some potential usernames (from a website, LinkedIn, OSINT) → validate them against AD
- You have one password and many usernames → password spray across all valid users
- You want to be stealthy → Kerberos-based auth attempts are less monitored than SMB
How do you use it?
Username enumeration
# Enumerate usernames from a wordlist against the DC $ kerbrute userenum --dc DC01.corp.local -d corp.local /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt # With a custom username list $ kerbrute userenum --dc 10.10.10.10 -d corp.local users.txt # Output shows: 2024/01/15 10:30:00 > [+] VALID USERNAME: jsmith@corp.local 2024/01/15 10:30:01 > [+] VALID USERNAME: administrator@corp.local 2024/01/15 10:30:01 > [+] VALID USERNAME: svc_sql@corp.local <-- save these, this list feeds password spraying next
Common AD username formats: jsmith, j.smith, john.smith, smithj. If you found names from a company website or LinkedIn, generate all common formats. Tools like username-anarchy can help: username-anarchy -i names.txt
Password spraying
# Spray one password against a user list $ kerbrute passwordspray --dc DC01.corp.local -d corp.local valid_users.txt 'Welcome1!' # Common first passwords to try: # Welcome1!, Password1!, Company2024!, Season+Year (Summer2024!) # Check the company's password policy first if you can 2024/01/15 10:35:00 > [+] VALID LOGIN: svc_backup@corp.local:Welcome1! <-- a service account hit, worth checking its group memberships
Password spraying can lock accounts. Before spraying, try to determine the lockout policy. If you can't, spray one password at a time with a 30-minute gap between attempts. Never try more than 2-3 passwords per user in a short period.
Brute-force a single user
# Try a password list against a single user $ kerbrute bruteuser --dc DC01.corp.local -d corp.local /usr/share/wordlists/rockyou.txt svc_backup # Only use this against service accounts that typically don't lock out
What do you do with the output?
Valid usernames
- Save them to a file: You'll need this list for password spraying, AS-REP roasting, and Kerberoasting
- AS-REP roast them:
GetNPUsers.py corp.local/ -usersfile valid_users.txt -no-pass - Password spray: Try common passwords via kerbrute or CrackMapExec
- Look for patterns: Service accounts (
svc_*), admin accounts (adm_*,da_*): these are high-value targets
Valid credentials
- Check group memberships: Is this user a local admin anywhere? In privileged groups?
- Run BloodHound:
bloodhound-python -d corp.local -u user -p pass -c all - Kerberoast: Any valid domain user can request SPNs,
GetUserSPNs.py corp.local/user:pass - Try WinRM/SMB/RDP:
evil-winrm,crackmapexec smb,xfreerdp
Common mistakes
- Spraying too fast: 3 wrong attempts = lockout on most domains. One password, wait 30 minutes, next password
- Wrong domain name: Kerbrute needs the FQDN (
corp.local), not the NetBIOS name (CORP) - Not adding DC to /etc/hosts: If using the hostname, make sure it resolves:
echo "10.10.10.10 DC01.corp.local corp.local" >> /etc/hosts - Skipping username enumeration: Don't go straight to spraying. Enumerate first, it's free (no creds needed) and tells you exactly which accounts exist
- Only using generic wordlists: Add company-specific names to your list.
admin,administrator,svc_sql,svc_backup,helpdeskare common AD accounts
Check yourself
Answer each question out loud or on paper first, then open it. Retrieving the answer teaches you more than rereading the page.
Why enumerate usernames before you spray a password?
You spray three passwords against one user in a minute and the account locks. What should the process have looked like?
Kerbrute returns no results and you gave it the domain as CORP. What is wrong?
corp.local, not the NetBIOS name.Why is Kerbrute considered stealthier than an SMB-based username check?
A generic wordlist finds nothing. What do you add?
svc_sql, svc_backup and helpdesk.