Web Security's own rate-limiting lesson covered brute force — guessing a password through sheer repetition. Credential stuffing is a related but genuinely different attack, using passwords that are already known to be real, and it defeats some of brute force's own defenses almost entirely.
3 min read
Credential stuffing uses email/password pairs leaked from other, unrelated breaches — an attacker isn't guessing at all, they're trying real, previously valid credentials directly, betting on how often people reuse the same password across multiple sites. This single difference changes the defense calculus completely: rate limiting per account (Web Security's own defense against ordinary brute force) does little to stop it, because the attacker isn't hammering one account with thousands of guesses — they're trying one guess each against thousands or millions of different accounts, each individual attempt looking exactly like a normal login.
A password that's already appeared in a public breach corpus (the "Have I Been Pwned" Pwned Passwords dataset being the most widely used) is a genuinely bad password regardless of how "strong" it looks by length and character-variety rules — it's specifically the kind of password credential stuffing targets, because it's already known to attackers by definition. Checking a user's chosen password against such a list at signup (and, ideally, periodically for existing accounts) and requiring a different one closes this specific gap directly, in a way that ordinary password-complexity rules (requiring a symbol, a number) never actually address.
Auth's own MFA lesson already established multi-factor authentication's core value — even if an attacker has the exact correct, leaked password, a second factor they don't also have stops the login cold. Credential stuffing is precisely the scenario where this matters most: the first factor (the password) being entirely correct is the whole premise of the attack, and MFA is the one defense that remains fully effective regardless.
Individually, each request looks like:
"a real user, trying a real (leaked) password, once" — NORMAL
In aggregate, the pattern looks like:
Thousands of DIFFERENT accounts, each receiving exactly ONE
login attempt, from a small number of IPs, in a short window
Because no single request looks malicious, detecting credential stuffing generally requires looking at the aggregate pattern across many attempts — a spike in login attempts against many different accounts, an unusually high failure-then-success ratio clustered in a short window, a login velocity implausible for a human typing — rather than any single request's own content. This is exactly the kind of anomaly Web Security's own logging-and-monitoring lesson argued needs active monitoring, not just logs nobody reviews, to actually catch in time.
A CAPTCHA adds real friction for every legitimate user attempting to log in, and determined attackers increasingly use CAPTCHA-solving services (automated or human-powered) that defeat it anyway — it's a real, partial speed bump, not a strong guarantee. Behavioral and device-fingerprinting signals (mouse movement patterns, time-to-fill-a-form, a browser's specific rendering fingerprint, whether a request's headers are consistent with the browser it claims to be) let a system distinguish likely-automated traffic from likely-human traffic without forcing every single legitimate user through an extra, annoying step — reserving a CAPTCHA (or blocking outright) specifically for traffic that already looks suspicious by these other signals, rather than applying it universally to every login attempt regardless of how it behaves.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What makes credential stuffing different from ordinary brute force?
2. Why is per-account rate limiting a weak defense against credential stuffing specifically?
3. Why does MFA remain effective against credential stuffing even when the attacker has a correct, leaked password?
Application Security & Secure Coding