Skip to content

/notes / credential-stuffing

Credential stuffing beats brute force. Here's how you stop it.

Enerik Sina··7 min read

Brute force is dead as a serious attack on any service with a rate limit. Nobody is iterating aaaa, aaab, aaac against your login endpoint. What replaced it is far more efficient: credential stuffing — replaying username/password pairs leaked from one service against another, on the bet that people reuse passwords. The bet pays. Reuse estimates consistently land above 60%, and a stuffing campaign with a fresh combolist can see success rates of 0.1–2%. Against a list of a hundred million pairs, that is a lot of accounts.

Why it's hard to stop

Each individual stuffing attempt looks like a legitimate login: one username, one plausible password, one try. There is no guessing pattern to detect on a per-account basis — the attacker already has the password, they just don't know if it still works here. The volume hides in distribution: campaigns rotate through residential proxy networks (real ISP addresses rented from infected or 'monetized' consumer devices), spread attempts across days, and randomize timing. Block a datacenter ASN and you've blocked nothing; the traffic was never coming from datacenters.

  • Low-and-slow: a few attempts per IP per hour stays under naive rate limits
  • Residential proxies: source IPs with clean reputations and real-user history
  • Combolist hygiene: attackers pre-validate format, dedupe, and target-match emails before the run
  • Tooling: OpenBullet-style frameworks ship with per-site configs traded openly

The defense stack

No single control stops stuffing; the goal is to make each layer remove a slice of the attack until the economics break. The layers that earn their keep, roughly in order of effort:

  • Breached-password screening: check submitted passwords against known-leaked corpora (k-anonymity APIs make this private). Stops the attack at its source — the reused password.
  • Per-account and global failure-rate monitoring: stuffing shows up as a fleet-wide rise in failed logins with normal per-IP counts. Alert on the aggregate, not the IP.
  • TLS and header-order fingerprinting at the edge: stuffing frameworks rarely match a real browser below HTTP, even with rotating proxies.
  • Behavioral signals on the login page: real users move a cursor and take time; replay scripts do not.
  • MFA and passkeys: a stolen password without a second factor is a failed attack. Passkeys end password reuse entirely — they're the long-term answer.

What success looks like

You don't measure anti-stuffing by blocked requests — bots are happy to be blocked cheaply; they'll just rotate. You measure it by account-takeover rate and by attacker cost. When a campaign has to burn residential bandwidth, solve behavioral challenges, and still hits MFA on every valid pair, the cost per takeover rises until your service stops being worth the combolist. That is the actual win condition: not zero bots, but negative ROI for the operator.