# how to write a detection rule for credential stuffing

## TL;DR
Count failed logins by source IP over a short window and fire when one IP fails a lot of logins across a lot of different usernames. 20 failures across 5 or more usernames in 5 minutes is a sane starting point. Tune against a week of your own data before you trust it, because shared VPN and NAT ranges will set it off constantly.

```text
how to write a detection rule for credential stuffing
```

## Use this when
- your login endpoint is getting hammered and you need a rule that fires on it
- you are setting up login detection in Splunk, Elastic, or Microsoft Sentinel
- you need to tell credential stuffing apart from plain brute force
- leadership asked "are we being attacked" and you need a number, not a vibe

## Not for this skill when
- you need to stop phishing, not automated login abuse
- you are configuring password policy or account lockout (that is prevention, not detection)
- the attack is session hijacking or cookie theft, not login attempts
- you want a full bot-management product, not a log rule

## Steps
1. Pull a week of auth logs and learn your normal failure rate. In Splunk:
```spl
index=web sourcetype=auth status=401
| stats dc(username) as users, count as failures by src_ip
| sort - failures
| head 20
```
Expected: a short table of the worst IPs. Most teams see a handful of chronic offenders and a long tail of typos.

2. Write the core rule. Alert when one IP generates 20 or more failed logins across 5 or more distinct usernames within 5 minutes. The distinct-username part is what separates stuffing (a list of leaked creds) from one user fat-fingering a password.

3. Add a slow-stuffing rule for the sneaky ones. Alert when one account sees 5 or more failures from 3 or more different IPs within an hour. Attackers rotate IPs to dodge per-IP rules, so the per-account view catches them.

4. Add suppressions before the first alert. Exempt your corporate VPN egress ranges, load-balancer health checks, and test accounts. Stuffing rules are worthless if the first page is your own infra.

5. Attach a response action. Auto-block the IP for 24 hours at the WAF or firewall, and page the on-call with the IP, the username list, and the first-seen time. Detection without a response is just a log.

6. Backtest before you trust it. Run the rule against last week's data and eyeball every hit. If more than a third are false positives, raise the thresholds or add suppressions.

### Variant: distinguishing credential stuffing from password spraying
Spraying is one password tried against many accounts; stuffing is many leaked pairs. Flip the rule: one source IP, many usernames, and the same attempted password in a short window. If your logs hash the attempted password, group by that hash for a clean signal.

### Variant: writing the same rule in Elastic
In Kibana, use a threshold rule: group by source.ip, count events where the outcome is failure on the login dataset, and alert above 20 in 5 minutes. Add a unique count of user.name above 5 for the multi-username condition.

### Variant: rules for API keys instead of passwords
For service auth, alert on 401s grouped by API key ID or client ID instead of IP. A leaked key gets replayed from fresh IPs, so per-key thresholds (say 50 failures in 10 minutes) catch what per-IP rules miss.

## Why this happens
Big breach dumps give attackers millions of real username and password pairs, and plenty of people reuse passwords everywhere. Automated tools replay those pairs against every login form on the internet. The traffic looks like normal logins, just at scale, which is why you need a rule tuned to volume and username spread instead of reacting to single failures.

## Edge cases and pitfalls
- Shared NAT and VPN ranges make many users look like one attacker. Exempt or allowlist your known egress IPs.
- Mobile carrier IPs rotate, so one user can appear from many IPs. That makes per-account rules noisier on mobile apps, so raise the IP threshold there.
- Legit batch jobs and scripts that retry with a stale credential trip per-account rules. Inventory your service accounts first.
- Low-and-slow stuffing under your thresholds will pass. That is normal. Layers handle it: rate limiting and lockout catch what detection misses.
- Dont alert on single-user failures. Real users mistype passwords. The rule only earns its keep on volume plus spread.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_V6AUmeYNDgmNDE-ACeKv1Q
