Password spraying: The low-and-slow attack that per-account lockouts miss
Password spraying tries a few common passwords across many accounts, slipping under per-account lockouts. The signals it leaves and what stops it.
Password spraying is an attack that tries a small number of very common passwords against a large number of accounts. Each account sees only one or two failed attempts, so per-account lockouts and failed-attempt counters never trip. MITRE ATT&CK catalogs it as sub-technique T1110.003 under Brute Force.
MITRE states the purpose plainly: one password, or a small list of common ones, is tried against many different accounts to avoid the lockouts that would normally happen when brute forcing a single account. OWASP's summary is shorter still: testing a single weak password against a large number of different accounts.
That inversion is the whole problem. Almost every control guarding a sign-in endpoint counts failures per account, and a spray never gives any one account enough failures to count.
How is spraying different from credential stuffing and brute force?
The three attacks get grouped together because they all end in an unauthorized sign-in, but they start from different inputs and get past different controls:
We covered the first two in Credential stuffing vs. brute force attacks, and the mechanics of guessing at volume in What is a brute force attack?. This post is about the third row, because the detection problem it creates is different.
Why do per-account controls miss it?
Look at where the standard draws the boundary. NIST SP 800-63B-4 requires verifiers to limit consecutive failed attempts with a given authenticator on a single account to no more than 100, by disabling that authenticator. It's a sound requirement, and you should implement it. It's also scoped to one account, which is exactly the scope a spray avoids.
Two attempts per account over a weekend never get close to 100. And if the attacker's one password works on some account, a successful sign-in clears the slate: NIST says the verifier should disregard earlier failed attempts after a successful authentication.
Attackers tune for this deliberately. MITRE notes that adversaries may throttle spraying attempts to avoid triggering security alerts, and the documented pacing is slower than most teams expect. ATT&CK records APT28 tooling that, in spraying mode, made about four authentication attempts per hour per targeted account over several days or weeks. The Quad7 activity cluster went further, using a single sign-in attempt within 24 hours to stay under brute-force detection thresholds.
Tightening the per-account threshold doesn't fix this, and it costs you something. MITRE's account use policy guidance warns that too strict a policy may create a denial-of-service condition, with every account in the attack locked out. A lockout rule aggressive enough to catch one attempt per account per day locks out your customers.

What signals does spraying leave?
A spray is quiet per account and loud in aggregate. The shift is to stop asking "how many times did this account fail?" and start asking "how many accounts failed on the same password?"
MITRE's detection strategy for T1110.003 is built on exactly that: a high volume of authentication failures using a single password, or a small set, across many accounts within a defined time window. Its SaaS and SSO analytic is more specific, looking for sign-in failures from the same IP address using the same password against multiple user identities. Three signals are worth instrumenting.
Many accounts failing on the same password. This means correlating the submitted secret across failures, which you can do without storing it. Compute a keyed fingerprint of the submitted password with an HMAC under a key you rotate, record the fingerprint on the failure event, and never write the password itself. Treat the fingerprint as sensitive, keep retention short and rotate the key often: a fingerprint that stays stable across your whole user base turns a leaked auth log into a way to test whether two users chose the same password. A query over those events looks like this:
Those numbers are a starting point, not a standard. Baseline them against a week of your own failure traffic before you alert on anything. The second HAVING condition does the real work: many accounts with many attempts each is usually ordinary bot noise, while many accounts with close to one attempt each is the spray shape.
Plan for one false positive in particular: your own bulk operations produce the same shape. A forced password reset across a tenant sends a wave of users back to the sign-in form typing the same old password, and the query can't tell that apart from a spray. Exclude tenants with an active reset, or join against recent password-change events before the alert fires.
Failures spread across tenants from shared infrastructure. Source IP is a weak key here, but not a useless one. OWASP suggests correlating authentication traffic with IP intelligence, including hosting provider ranges, and notes that some providers, such as AWS, publish their IP address space. Plan for the opposite pattern too: OWASP warns against relying on a single predictable volume limit, and to account for many IP addresses each sending low but consistent traffic.
A successful sign-in right after a wave of failures. This is the signal that turns a detection into an incident. OWASP's notification guidance helps calibrate it: telling a user that someone tried a wrong password usually isn't useful, but if the correct password was entered and the MFA step then failed, the user should be told so they can change their password.
One more thing makes the whole picture quieter. OWASP notes that enumerating users first allows a harder-to-identify, lower-volume attack. If your sign-in flow tells an attacker which usernames exist, the spray that follows wastes no attempts and leaves a smaller footprint.
Which defenses actually work?
Block common and breached passwords at sign-up and password change. This targets the attack's input directly. NIST requires verifiers to check a new password against a blocklist of commonly used, expected or compromised values, which can include breach corpuses, dictionary words and context-specific words such as the service name or the username. On a match, the user has to choose another password and be told why. OWASP names Pwned Passwords as a free service for checking new passwords against breach data. NIST also says the blocklist should be large enough that an attacker is unlikely to guess a password before reaching the attempt limit.
While you're there, drop the composition rules. NIST requires at least 15 characters for passwords used as a single factor and says verifiers shall not impose other composition rules, such as requiring a mix of character types. Those rules are what produce Summer2026!, which is exactly the kind of password a spray list contains.
- Add a second velocity counter at tenant scope. Keep the per-account counter and run a wider one beside it. The query above is the detection; the control is wiring its output into an authentication decision. NIST explicitly allows for this, listing bot detection and challenges, increasing wait periods after failures, and risk-based techniques using IP address, geolocation, request timing or browser metadata. OWASP lists an IP address that has tried to sign in to multiple accounts as a trigger for requiring a second factor.
- MFA, and the accounts it can't cover. OWASP calls MFA by far the best defense against most password-related attacks, citing Microsoft analysis that it would have stopped 99.9% of account compromises, and MITRE lists it as a mitigation for T1110.003. The gap is non-human accounts. The joint advisory on SVR cloud access points out that service accounts have no human user behind them, so they can't easily be protected with MFA. For those, it recommends disabling accounts that are no longer needed, through a joiners, movers and leavers process, and creating canary service accounts that look valid but are never used legitimately, so any use of them is a strong signal.
- SSO moves the surface for enterprise tenants. Federating a tenant moves password verification to its identity provider and takes that tenant's passwords off your sign-in endpoint. It doesn't take them out of scope: MITRE notes that adversaries target SSO and cloud applications using federated authentication, as well as externally facing email such as Office 365.
What should you not rely on?
- IP-only rate limits. OWASP is direct: blocking IP addresses may stop less sophisticated attacks but shouldn't be the sole or primary defense, because it's easy to get around. Tooling is built for the bypass; OWASP notes that credential stuffing toolkits such as Sentry MBA have built-in support for proxy networks that spread requests across many IP addresses. The SVR advisory describes the same evasion at the nation-state end: residential proxies make traffic appear to come from ISP ranges, which makes IP-based defenses less effective.
- Lockouts on their own. Keep the per-account limit, because NIST requires it. Just don't count it as coverage: it works at the wrong scope for this attack, it resets on success, and tuning it down far enough to matter turns it into a denial of service against your own users.
What does a real campaign look like?
CISA advisory AA24-057A, "SVR Cyber Actors Adapt Tactics for Initial Cloud Access", was published on February 26, 2024. It was authored by the UK NCSC and co-sealed by NSA, CISA, the US Cyber National Mission Force, the FBI, Australia's ACSC, Canada's CCCS and New Zealand's GCSB. It covers the group known as APT29, Midnight Blizzard, the Dukes or Cozy Bear.
Its ATT&CK table maps T1110 Brute Force to one sentence: "The SVR use password spraying and brute forcing as an initial infection vector." The advisory describes two uses. Earlier SVR campaigns used brute forcing and password spraying to access service accounts, and on several occasions the actors got past password authentication on personal accounts using password spraying and credential reuse. Both targets are the ones ordinary sign-in defenses cover least well: accounts that can't hold a second factor, and accounts nobody is watching.
MITRE's T1110.003 page keeps a current list of procedure examples, which makes a useful checklist for testing your own detections.
Where should you start?
Run the cross-account query against your last month of authentication failures. If your auth events can't be grouped by a password fingerprint and a tenant ID, that's the first thing to build, before any new rule or threshold. And if the query comes back empty, don't read it as an all-clear. Read it as the first time you've been able to ask.