Skip to main content
HighProtected by PowerWAF

Password Spraying Attack

CategoryAuthentication & AccessOWASPA07:2021 โ€“ Identification and Authentication FailuresFirst seen2012Read time9 minVerified2026-03-11
DEFINITION

Password spraying is a type of brute force attack that tests a small number of commonly used passwords against a large number of user accounts simultaneously. Unlike traditional brute force that tries many passwords against one account (triggering lockout), password spraying tries one password against all accounts before moving to the next, evading account lockout policies while exploiting the statistical certainty that some users will have weak passwords.

How Password Spraying Attack Works

Password spraying exploits a fundamental tension in security design: account lockout policies protect individual accounts from brute force but cannot protect against attacks distributed across many accounts. If an organization has 10,000 users and the attacker tries just one password (e.g., 'Summer2026!'), statistically 1-3% of users will have that exact password, yielding 100-300 compromised accounts โ€” all without triggering a single lockout. The attack is particularly effective against enterprise environments using Active Directory, Microsoft 365, and other centralized identity systems.

1

Enumerate valid usernames

The attacker harvests valid usernames through multiple sources: LinkedIn scraping to derive corporate email formats (firstname.lastname@company.com), email harvesting from public records and data breaches, OSINT tools (theHarvester, Hunter.io), timing-based username enumeration on login pages (different response times for valid vs. invalid usernames), and Azure AD/Microsoft 365 user enumeration via publicly accessible APIs. A single organization can yield thousands of valid usernames.

2

Craft targeted password list

Instead of generic wordlists, the attacker creates a small, targeted password list based on the organization's context: company name + year (CompanyName2026), seasonal patterns (Winter2026!, Summer2026!), common patterns meeting complexity requirements (Welcome1!, Password123!, Qwerty@123), recently expired passwords with incremented numbers, sports teams or local references, and default passwords for new accounts. A focused list of 5-20 passwords is more effective than thousands of random ones.

3

Execute distributed low-velocity attack

The attacker tests one password against all enumerated accounts, then waits (often 30-60 minutes or longer) before trying the next password. This delay keeps the attempt count per account well below lockout thresholds (typically 3-5 attempts in 15-30 minutes). Advanced attackers distribute requests across multiple source IPs using cloud infrastructure, residential proxies, or compromised devices to avoid IP-based detection. Each password is tested against the entire user base before advancing.

4

Identify and exploit successful logins

The attacker monitors for successful authentication responses, which typically differ from failures in HTTP status codes, response headers, or redirect destinations. Each successful login is immediately tested for access scope: email, VPN, cloud services, internal applications. The attacker prioritizes accounts with administrative privileges, access to sensitive data, or positions that enable further social engineering (executives, IT staff, finance).

5

Establish persistence and escalate

Compromised accounts are used to establish persistence before the password is potentially reset: the attacker enrolls their own MFA device, creates mail forwarding rules, generates application passwords, or provisions OAuth tokens. High-value accounts are used for lateral movement within the organization โ€” accessing SharePoint documents, internal wikis, and other systems that rely on the same identity provider, progressively expanding access to more sensitive resources.

Real-World Examples

2024

Midnight Blizzard (Nobelium) attack on Microsoft

The Russian state-sponsored group Midnight Blizzard (formerly Nobelium, the SolarWinds attackers) used password spraying to compromise a legacy non-production Microsoft test tenant account that lacked MFA. From this initial foothold, they accessed Microsoft's corporate email systems and read emails of senior leadership and cybersecurity team members for several months. The incident demonstrated that even the world's largest technology companies are vulnerable to password spraying against accounts with inadequate protections.

2019

Iranian APT campaigns against US government

The US Department of Justice indicted Iranian hackers who conducted a massive password spraying campaign targeting over 7,998 accounts across 176 universities in 21 countries, 47 private companies, the United Nations, and US government entities. The attackers successfully compromised approximately 3,768 accounts, stealing over 31 terabytes of data worth approximately $3.4 billion in intellectual property.

2019

Citrix breach via password spraying

Attackers used password spraying to gain initial access to Citrix's internal network, subsequently accessing and downloading business documents for approximately six months before detection. The FBI alerted Citrix to the breach. The attackers, attributed to the IRIDIUM group, accessed approximately 6 TB of sensitive internal data. Citrix later confirmed that the initial access point was a combination of password spraying and credential stuffing against employee accounts.

Impact & Risk Assessment

Password spraying is one of the most effective initial access techniques used by both cybercriminals and nation-state actors. Its effectiveness stems from the mathematical certainty that in any large user population, some users will have weak passwords. A successful spray typically compromises 1-3% of targeted accounts, which in a 10,000-user organization means 100-300 accounts. The impact cascades: compromised email accounts enable business email compromise (BEC) and internal phishing; VPN access provides network-level access to internal resources; cloud admin accounts expose the entire cloud infrastructure. Microsoft's Digital Defense Report 2024 identified password spraying as the most common identity-based attack vector, responsible for over one-third of enterprise account compromises.

How to Detect Password Spraying Attack

Detecting password spraying requires shifting from per-account analysis to cross-account pattern recognition. Monitor for: simultaneous failed login attempts across many accounts with the same password (the defining spray pattern), failed login spikes across the organization even when no individual account exceeds lockout thresholds, authentication attempts from cloud hosting IPs or known proxy services, login attempts outside business hours across many accounts, successful logins immediately following a pattern of distributed failures, and geographic anomalies (login attempts from countries where the organization has no employees). Implement centralized authentication logging that correlates events across all identity providers (AD, Azure AD, Okta, LDAP). Deploy SIEM rules specifically designed to detect low-and-slow password spraying patterns. Monitor for OAuth token generation and MFA enrollment changes following successful authentication from unusual sources.

How to Prevent Password Spraying Attack

Implement multi-factor authentication for all accounts โ€” MFA neutralizes password spraying even when weak passwords are discovered, because the attacker lacks the second factor. Deploy passwordless authentication (FIDO2, passkeys) where possible to eliminate password-based attacks entirely. Enforce password policies that ban common patterns: check against breach lists (HaveIBeenPwned), block company name variations, seasonal patterns, and keyboard walks. Implement smart lockout that considers distributed patterns (Azure AD Smart Lockout, similar for other providers) rather than only per-account thresholds. Deploy conditional access policies that restrict authentication based on location, device compliance, and risk signals. Use honeypot accounts โ€” decoy accounts that generate immediate alerts when authentication is attempted. Implement login rate limiting that considers cross-account patterns, not just per-account rates. Regularly audit service accounts, legacy accounts, and non-production accounts, which are frequently overlooked and lack MFA. Disable legacy authentication protocols (IMAP, POP3, SMTP AUTH) that don't support MFA.

Code Examples

Detection: Cross-account spray pattern analysis
from collections import defaultdict
from datetime import datetime, timedelta

def detect_password_spray(auth_logs, window_minutes=30, threshold=10):
"""Detect password spraying by identifying coordinated failed logins
across multiple accounts within a time window."""

# Group failed logins by time window
windows = defaultdict(lambda: {
'source_ips': set(),
'target_accounts': set(),
'failed_count': 0,
'timestamps': []
})

for log in auth_logs:
if log['status'] != 'failed':
continue

# Round timestamp to window
window_key = log['timestamp'].replace(
minute=(log['timestamp'].minute // window_minutes) * window_minutes,
second=0, microsecond=0
)

w = windows[window_key]
w['source_ips'].add(log['source_ip'])
w['target_accounts'].add(log['username'])
w['failed_count'] += 1
w['timestamps'].append(log['timestamp'])

alerts = []
for window_start, data in windows.items():
# Spray signature: many accounts, few IPs, concentrated time
accounts_hit = len(data['target_accounts'])
unique_ips = len(data['source_ips'])

if accounts_hit >= threshold:
# High ratio of targeted accounts to source IPs = spray
spray_score = accounts_hit / max(unique_ips, 1)

if spray_score >= 5: # 5+ accounts per IP = likely spray
alerts.append({
'type': 'password_spray_detected',
'severity': 'critical' if accounts_hit > 100 else 'high',
'window_start': window_start,
'accounts_targeted': accounts_hit,
'source_ips': list(data['source_ips']),
'total_failures': data['failed_count'],
'spray_score': round(spray_score, 1)
})

return alerts
Prevention: Custom banned password checker
import re
import hashlib
import requests
from datetime import datetime

class PasswordPolicyChecker:
"""Enterprise password policy with spray-resistant rules"""

def __init__(self, company_name):
self.company_name = company_name.lower()
self.company_variants = self._generate_variants(company_name)

def _generate_variants(self, name):
"""Generate common leetspeak and pattern variants"""
base = name.lower()
variants = {base}
# Common substitutions
subs = {'a': '@4', 'e': '3', 'i': '1!', 'o': '0', 's': '$5'}
for char, replacements in subs.items():
for r in replacements:
variants.add(base.replace(char, r))
return variants

def check(self, password):
"""Returns (is_valid, rejection_reason)"""
pw_lower = password.lower()

# Block company name variants
for variant in self.company_variants:
if variant in pw_lower:
return False, 'Password contains company name'

# Block seasonal patterns
seasons = ['spring', 'summer', 'autumn', 'fall', 'winter']
current_year = datetime.now().year
for season in seasons:
for year in range(current_year - 2, current_year + 2):
if f'{season}{year}' in pw_lower:
return False, 'Password contains predictable seasonal pattern'

# Block common base passwords
common_bases = [
'password', 'welcome', 'qwerty', 'admin', 'changeme',
'letmein', 'monkey', 'dragon', 'master', 'login'
]
for base in common_bases:
if base in pw_lower:
return False, 'Password contains common word'

# Block keyboard walks
keyboard_walks = [
'qwerty', 'qwer', 'asdf', 'zxcv', '1234', '4321',
'qazwsx', 'qwertyui'
]
for walk in keyboard_walks:
if walk in pw_lower:
return False, 'Password contains keyboard pattern'

# Check HaveIBeenPwned (k-anonymity API)
if self._check_hibp(password):
return False, 'Password found in known data breaches'

return True, None

def _check_hibp(self, password):
"""Check password against HaveIBeenPwned using k-anonymity"""
sha1 = hashlib.sha1(password.encode()).hexdigest().upper()
prefix, suffix = sha1[:5], sha1[5:]
resp = requests.get(f'https://api.pwnedpasswords.com/range/{prefix}')
return suffix in resp.text

PowerWAF automatically blocks Password Spraying Attack at the edge.

Deploy in minutes. No code changes required. Free plan available.

Free plan spots are limited

Frequently Asked Questions

Traditional brute force tries many passwords against one account, triggering lockout after a few attempts. Password spraying inverts this: it tries one password against many accounts, staying below each account's lockout threshold. Brute force is effective against individual targets with no lockout; spraying is effective against organizations with standard lockout policies. Spraying trades depth (fewer passwords per account) for breadth (many accounts tested).
Enterprise environments have thousands of accounts, making it statistically certain that some users have weak passwords โ€” even with complexity requirements. Users create predictable passwords by appending numbers/symbols to common words (Company2026!, Welcome1!). Large organizations also have legacy accounts, service accounts, and shared accounts that often have weaker passwords and lack MFA. Centralized identity systems (Active Directory) mean one compromised credential provides access to multiple services.
No. Standard lockout policies (e.g., lock after 5 failures in 30 minutes) only track per-account attempts. Password spraying tests 1-2 passwords per account at a time, never reaching the lockout threshold. Smart lockout solutions that analyze cross-account patterns provide better protection, but the most effective defense is MFA, which makes stolen passwords insufficient for access.
Beyond standard complexity requirements, block: the company name and all variations (C0mp4ny, CompanyName2026), seasonal patterns (Spring2026!, Winter2025!), common base words (Password, Welcome, Qwerty, Admin, Changeme), keyboard walks (qwer1234, Zxcvbn!1), and any password appearing in known breach databases. Azure AD's custom banned password lists and similar features in other identity providers make this enforcement practical at scale.
Common techniques: LinkedIn scraping to derive email formats (80%+ of companies use firstname.lastname@domain.com), email verification APIs, organization directories and annual reports, conference attendee lists, OSINT tools (theHarvester, Hunter.io), and Azure AD / Microsoft 365 user enumeration endpoints that confirm whether an account exists. Some login pages also leak username validity through different error messages or response timing for valid vs. invalid usernames.