Credential stuffing: passwords that leaked somewhere else

Credential stuffing tries username and password pairs exposed in a breach of some other service, on the chance that the same person reused them with you. It is not guessing: guessing tries many passwords against one account, while this tries one password against many accounts, and that password is already known to be real. The difference decides every defence here.

Section Bots Updated Signals three

Quick facts

What it takes
Accounts, and whatever those accounts can reach
Typical volume
Spread thin: many accounts, few attempts each
In your logs
Successful logins mixed into a large number of ordinary failures
Cost of blocking wrongly
Locked-out customers, and a support queue that arrives all at once

Why it works, and where the defect is

The mechanism depends on one fact about people rather than on any weakness in your system: the same password gets used in more than one place. When a service is breached, the pairs from it become usable everywhere that person reused them.

Two consequences follow, and both are uncomfortable.

Your login form is working correctly. It received a valid password and accepted it. Nothing was bypassed, and no rule about length or characters would have made a difference.

Your exposure depends on other people's security. A breach you have no relationship with determines how many of your accounts are at risk, and you will not be told when one happens.

The signals

Three, and the first is the one that makes this identifiable at all.

An unusual failure ratio. Ordinary login traffic fails sometimes; people mistype and forget. Stuffing produces failures at a rate no genuine population reaches, because most pairs are wrong for your site. That ratio, measured across the whole login endpoint rather than per source, is the clearest indicator available.

Breadth without depth. Many distinct accounts, one or two attempts each. The opposite shape from guessing, which hammers a single account, and the reason per-account attempt limits alone do not see it.

Logins without the rest of the visit. Sessions that begin at the login endpoint with no browsing before it, no assets loaded, and no behaviour afterwards resembling how your customers use the product.

Sources are usually numerous and unremarkable individually, which is covered on bot detection: reputation helps and does not decide.

Before you lock accounts

Read before changing anything

Warning: locking an account after a number of failed attempts is the reflex response, and against this attack it converts an intrusion attempt into a denial of service against your own users.

A LOCKOUT FIRED BY SOMEBODY ELSE'S ATTEMPTS THE ATTEMPTS ARRIVE SOURCE ACCOUNTS THAT BELONG TO YOUR CUSTOMERS THE LOCKOUT FIRES ON THE ACCOUNT BEING TRIED WHO IT LANDS ON THE CUSTOMER LOCKED OUT OF THEIR OWN ACCOUNT THE ATTACKER UNAFFECTED — MOVES TO THE NEXT ACCOUNT // what targets the attacker is a limit on the source, not a penalty on the account
// the defence lands on the party that did nothing

The reason is arithmetic. The attacker is submitting attempts against accounts that belong to your customers; a lockout triggered by those attempts locks the customer out, not the attacker. Where the attack covers many accounts, so does the lockout, and your support queue receives the consequences of a defence you chose.

Where lockout is used at all, it should be temporary, expressed as a delay that grows rather than a door that closes, and paired with a way for the real owner to recover without contacting anyone. The measure that targets the attacker is a limit on the source and a challenge on the endpoint, not a penalty on the account being tried.

What actually reduces the risk

Ordered by how much they change the outcome.

Second factors. A password that is correct stops being sufficient. This is the only measure that addresses the mechanism rather than its traffic, and everything else is mitigation around it.

Checking passwords against known exposures. At registration and at change, refusing credentials already known to be public removes the reuse this attack depends on, prospectively.

Limits and challenges on the login endpoint, applied per source and in aggregate rather than per account, for the reason described above.

Signals about the session, such as whether the device and location are consistent with the account's history. Useful, and they must degrade gracefully: people travel, replace phones, and use borrowed computers.

Telling the account owner. A notification of a login from a new device converts a silent compromise into something the person can act on, and it costs nothing when it is a false alarm.

Where an attempt succeeds, what happens next is a different subject: the account is under someone else's control, and the response belongs to account takeover handling rather than to traffic filtering.

False positives: who else fails to log in

The obligatory section, and here the lookalikes are ordinary people having a bad day.

Anyone whose password manager holds an old password, which produces repeated failures from a legitimate owner on a legitimate device.

Shared offices and networks. Many people logging in from one address, some of them failing, looks like a distributed attempt from a single source.

People who genuinely forgot, which correlates with accounts used rarely, meaning the customers you most want to bring back.

Your own systems. Health checks that log in, integration tests, and support tooling that authenticates as a user.

The pattern across all four: real failures cluster around one account or one address, while stuffing spreads. Deciding on the aggregate shape rather than on individual failures is what separates them.

What it looks like when it succeeds

The successful attempts are the ones your login metrics hide.

A campaign that tries many accounts and succeeds on a few produces a success rate that barely moves your averages. The compromised accounts then behave normally at first: a login, a look at what is there, and nothing that any threshold notices. Damage arrives later, when the access is used or sold.

ONE SEQUENCE HAS NO INNOCENT EXPLANATION ONE SOURCE, ACROSS MANY ACCOUNTS FAILED, FAILED, FAILED… SUCCEEDED TREAT IT AS A COMPROMISE UNTIL SHOWN OTHERWISE // the other tell: a login with no plausible activity afterwards // a success rate that barely moves your averages hides both
// the successful attempts are the ones your login metrics hide

Two habits surface it. Compare successful logins against the sessions that follow them, since a login with no plausible activity afterwards is unusual. And treat a successful login from a source that failed repeatedly across other accounts as a compromise until shown otherwise, because that sequence has no innocent explanation.

Recovery for those accounts is not a filtering question, and it should be decided before it is needed: what gets invalidated, what the owner is told, and how they regain access.

Handling this as part of the stack

Bridge WAF inspects login traffic at the edge: credential stuffing is one of the named rule categories, matches are recorded in monitor mode and refused in block, and rate limiting is applied per domain rather than per account — so watch the record first, and let it show what enforcement would have refused. What no filtering layer provides is the structural fix: second factors and exposure checks live in your authentication, and they are what make a correct-but-stolen password insufficient. See what the platform offers at Bridge CDN.

Questions

What is credential stuffing?

Trying username and password pairs exposed elsewhere against your service, on the expectation that some people reused them. Nothing is guessed and nothing is broken: the pairs are known to have worked somewhere, and the only question is how many of your customers overlap.

How is it different from brute force?

Guessing attacks one account with many passwords, which makes it loud on that account and easy to rate limit. Stuffing attacks many accounts with a single password each, and that password is already known to work somewhere, so it is quiet everywhere and visible only in aggregate.

Do strong password rules stop it?

No, and this is the point people find hardest. The password being tried was already accepted by another service and may satisfy every rule you impose. Complexity requirements address guessing; they have no effect on a password that is already known.

Should I lock accounts after failed attempts?

Carefully, because a lockout triggered by somebody else's attempts locks out your customer and hands anybody a deliberate way to deny them service. Growing delays, limits applied to the source rather than the account, and challenges achieve the same protection without creating that second problem.

What is the strongest defence?

A second factor, because it changes the arithmetic rather than the odds. It makes a correct password insufficient on its own, which means the technique stops working entirely against any account that has one, whatever was exposed elsewhere and however many pairs are tried.

How do I spot it in logs?

By the shape rather than the volume: a failure ratio in aggregate that no genuine population of customers produces, spread across a great many accounts with only a few attempts against each. Per-account counters see nothing unusual, which is why the aggregate view is required.

Where the platform sits

On the traffic rather than on the customer being tried. The structural fix lives in your authentication.

off

Nothing is counted at the login endpoint and nothing is recorded.

monitor

The aggregate failure shape is visible before any response lands on anybody.

block

The response falls on the traffic, and each decision has a record behind it.

The firewall layer is included with Bridge CDN. Start in monitor: nothing is refused until you decide it should be.

Get started