Key takeaways
- Modern login attacks come from thousands of IP addresses, each trying only once or twice, so per-IP limits and blocklists rarely trigger.
- The attackers use email and password pairs leaked from other sites (credential stuffing), hoping people reuse passwords. One or two tries per account is enough.
- Locking accounts backfires: attackers can lock out your real users on purpose.
- The password check itself is deliberately slow and expensive, so a large attack can become an outage even if every guess fails.
- The fix: decide early, verify later. Score each request cheaply, let low risk through, challenge medium risk, and drop high risk before it reaches the expensive check.
You stop a botnet at the login page by deciding who deserves the expensive password check, not by checking passwords harder. A recent reel framed this as an interview question, and it is a good one, because the obvious answers, block the IPs and lock the accounts, both fail. Conceptdigital builds web apps and internal tools, and login abuse is one of the first things we harden before a client launches.
Key definition: Credential stuffing is an automated attack that tries username and password pairs leaked from other websites, betting that people reuse passwords. bcrypt is a password-hashing method that is deliberately slow, so stolen password databases are hard to crack.
Why doesn't blocking IP addresses work?
Because no single address does anything suspicious. A modern botnet spreads its attempts across thousands of residential and cloud IP addresses, and each one sends only a handful of requests. A rule like "block any IP with more than five failed logins" never fires. OWASP's credential stuffing guidance makes the same point: attackers rotate addresses precisely to slip under per-IP limits.
Why not just lock the account after a few failures?
Two reasons. First, credential stuffing only tries each account once or twice, so a five-strike lockout rarely triggers. Second, when it does, you have handed attackers a weapon: they can lock real users out on purpose by failing logins for them. OWASP's authentication guidance warns about exactly this denial-of-service risk and recommends throttling and challenges over hard lockouts.
Why can a failed login attack take your site down?
Because checking a password is the most expensive thing your login does, by design. Passwords should be stored with a slow hash such as bcrypt; OWASP's password storage guidance recommends a work factor of 10 or more. That slowness is what makes a stolen database hard to crack. It also means every fake login attempt burns real CPU.
The arithmetic is simple. At 10,000 attempts a minute, with each check costing around 100 milliseconds of CPU, your servers spend about 1,000 CPU-seconds a minute on bots: roughly 17 cores doing nothing but rejecting fake passwords. Real users then queue behind them, and the attack becomes an outage.
So what actually works?
Put a cheap decision in front of the expensive one. Before any password is checked, score each request using signals that cost almost nothing to read:
- How the connection introduces itself. When a client opens a secure (TLS) connection, it announces which ciphers and extensions it supports, and in what order. A real iPhone app and a Python script produce different patterns, even when both claim to be an iPhone. These patterns are summarised as fingerprints such as JA4, and services like Cloudflare expose them to your rules.
- How this kind of client is doing. If most login attempts from one fingerprint fail, that fingerprint is probably a bot, however many IPs it uses.
- Whether the device is familiar. A browser or phone that has logged in successfully before is far lower risk than one never seen.
No single signal is enough, because a determined attacker can fake any one of them. Combined, they are expensive to fake at scale.
What do you do with the score?
Three lanes:
| Risk | What happens | Who it affects |
|---|---|---|
| Low | Straight to the password check | Almost every real user, who notices nothing |
| Medium | A CAPTCHA or similar challenge first | A few real users on new devices, and cautious bots |
| High | Dropped before it reaches bcrypt | Bots, which now cost the attacker more than they cost you |
This is the reel's summary, and it is the right one: don't just block, don't just lock out. Score each request cheaply, challenge the doubtful ones, and protect the slow, expensive step behind it.
What should a small team do first?
You rarely need to build the scoring yourself:
- Put the app behind a service with bot management, such as Cloudflare, and turn on its bot rules for your login route.
- Rate-limit the login route by fingerprint and by account, not only by IP.
- Replace hard lockouts with challenges: a CAPTCHA or an email confirmation after unusual failures.
- Check new passwords against known breaches at sign-up, as NIST's digital identity guidelines recommend, so stuffed credentials are less likely to work at all.
- Offer passkeys or two-factor login, which make leaked passwords far less useful.
- Watch the failure rate on your login route. A sudden rise in failed logins with no rise in real sign-ins is the signature of credential stuffing.
Frequently asked questions
Is this only a problem for big companies?
No. Credential stuffing is automated and cheap, so attackers run it against any login page they find, including small business apps and client portals. Smaller teams are often hit harder, because they have less spare server capacity to absorb it.
Will a CAPTCHA annoy my users?
Only if everyone sees it. With risk scoring, most real users go straight through, and only unusual cases, like a new device or a burst of failures, see a challenge.
Can bots fake a TLS fingerprint?
Yes, determined ones can, which is why the fingerprint is one signal among several, never the whole decision.
Should I lower the bcrypt cost so attacks are cheaper to absorb?
No. The slowness protects your users if your password database is ever stolen. Keep the work factor and protect the step in front of it instead.
About the author: Tengo Meskhi is CEO of Conceptdigital. He was previously at McKinsey and QuantumBlack, and Deputy CIO at Bank of Georgia.
If you run a login page and want a second pair of eyes on how it would hold up against an attack like this, we are happy to look at it with you. Book a 30-minute call.