<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: detecting-credential-stuffing
description: >-
  Detect and mitigate credential stuffing attacks using login anomaly analysis,
  rate limiting bypass detection, credential breach correlation, and behavioral
  analytics to distinguish automated attacks from legitimate authentication.
domain: cybersecurity
subdomain: identity-access-management
tags:
  - credential-stuffing
  - account-takeover
  - brute-force
  - rate-limiting
  - bot-detection
  - authentication
  - siem
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1110.004"]
---

# Detecting Credential Stuffing

## Overview

Credential stuffing uses stolen username/password pairs from data breaches to
compromise accounts across services where users reuse passwords. Unlike brute-force,
credential stuffing uses valid credentials at low velocity to evade rate limiting.
Detection requires correlating failed login patterns, geographic anomalies, user-agent
fingerprinting, and breach database cross-referencing.

Mode: `[MODE: BLUE]` for detection engineering; `[MODE: RED]` for attack simulation.

MITRE ATT&CK: T1110.004 (Credential Stuffing)

## Prerequisites

- SIEM platform (Splunk, Elastic, Sentinel) with authentication logs
- WAF with bot detection capabilities (Cloudflare, AWS WAF, Akamai)
- Python 3.10+ with `requests`, `pandas`
- HIBP API key for breach correlation
- Authentication logs with: timestamp, username, source IP, user-agent, result

## Key Concepts

### Attack Indicators

| Indicator | Description | Confidence |
|-----------|-------------|------------|
| Distributed source IPs | Same credentials from many IPs | High |
| Low failure rate | Valid breached creds succeed more than brute-force | Medium |
| Sequential usernames | Alphabetical or list-ordered login attempts | High |
| Uniform user-agent | Same UA string across many accounts | Medium |
| Off-hours activity | Login attempts during unusual hours | Low |
| Geographic impossibility | Logins from multiple countries within minutes | High |
| Residential proxy IPs | Traffic from residential proxy networks | Medium |

### Sigma Detection Rules

```yaml
title: Credential Stuffing — Multiple Failed Logins from Single IP
id: a3b2c1d0-1234-5678-9abc-def012345678
status: experimental
description: Detects multiple failed login attempts from a single IP targeting different accounts
logsource:
  category: authentication
  product: windows
detection:
  selection:
    EventID: 4625
  timeframe: 5m
  condition: selection | count(TargetUserName) by IpAddress > 10
falsepositives:
  - NAT gateways serving multiple users
  - Corporate VPN exit nodes
level: high
tags:
  - attack.t1110.004
  - attack.credential_access
```

```yaml
title: Credential Stuffing — Distributed Attack Pattern
id: b4c3d2e1-2345-6789-abcd-ef0123456789
status: experimental
description: Detects same username targeted from multiple IPs in short timeframe
logsource:
  category: authentication
  product: windows
detection:
  selection:
    EventID:
      - 4625
      - 4624
  timeframe: 10m
  condition: selection | count(IpAddress) by TargetUserName > 5
falsepositives:
  - Users with multiple devices authenticating simultaneously
level: medium
tags:
  - attack.t1110.004
  - attack.credential_access
```

### Splunk Detection Query

```spl
index=auth sourcetype=authentication action=failure
| bin _time span=5m
| stats count dc(user) as unique_users values(user) as users by src_ip _time
| where unique_users > 10 AND count > 20
| sort -count
```

## Workflow

### Step 1: Collect Authentication Logs

```bash
# Export authentication events
# Windows Event Log
wevtutil qe Security /q:"*[System[(EventID=4625 or EventID=4624)]]" /f:json > /tmp/auth_events.json

# Linux auth.log
grep -E "Failed password|Accepted password" /var/log/auth.log > /tmp/auth_events.txt

# Azure AD Sign-in Logs
az monitor activity-log list --resource-type Microsoft.AAD --output json > /tmp/azure_auth.json
```

### Step 2: Analyze with Agent Script

```bash
node scripts/agent.js --input /tmp/auth_events.json --output /tmp/stuffing_findings.json
node scripts/agent.js --input /tmp/auth_events.json --threshold 10 --timewindow 300
```

### Step 3: Correlate with Breach Data

```bash
# Check if targeted accounts appear in known breaches
node scripts/agent.js --input /tmp/auth_events.json --hibp --output /tmp/breach_correlation.json
```

### Step 4: Implement Mitigations

```bash
# WAF rate limiting rule (AWS WAF example)
aws wafv2 create-rate-based-rule \
  --name "LoginRateLimit" \
  --scope REGIONAL \
  --rate-limit 100 \
  --action '{"Block":{}}' \
  --visibility-config '{"SampledRequestsEnabled":true,"CloudWatchMetricsEnabled":true,"MetricName":"LoginRateLimit"}'
```

## Verification

- [ ] Authentication logs capture source IP, user-agent, and geographic data
- [ ] Rate limiting applied to login endpoints (per-IP and per-account)
- [ ] CAPTCHA or proof-of-work challenge triggered after failed attempts
- [ ] Account lockout policy with exponential backoff (not permanent lockout)
- [ ] Breached credential detection integrated (HIBP API or local hash check)
- [ ] Alerting configured for credential stuffing indicators
- [ ] Residential proxy IP lists updated and monitored
- [ ] MFA enforced — renders credential stuffing ineffective

## References

- [OWASP Credential Stuffing Prevention](https://owasp.org/www-community/attacks/Credential_stuffing)
- [MITRE ATT&CK T1110.004](https://attack.mitre.org/techniques/T1110/004/)
- [Have I Been Pwned API](https://haveibeenpwned.com/API/v3)
- [Cloudflare Bot Management](https://www.cloudflare.com/products/bot-management/)
