SC-041: Credential Stuffing at Scale¶
Scenario Header
Type: Account Takeover / Fraud | Difficulty: ★★★★☆ | Duration: 2–3 hours | Participants: 4–8
Threat Actor: Financially motivated cybercriminal group — credential stuffing and loyalty fraud
Primary ATT&CK Techniques: T1110.004 · T1078.004 · T1589.001 · T1566.001 · T1531 · T1496 · T1583.003
Threat Actor Profile¶
HYDRA SWARM is a synthetic financially motivated threat group specializing in large-scale credential stuffing campaigns targeting loyalty and rewards programs. The group operates as a service — acquiring breached credential databases from underground markets, operating rotating residential proxy infrastructure, and selling compromised loyalty accounts through dedicated reseller channels.
HYDRA SWARM's operational model is industrialized: they maintain a custom Python-based credential testing framework capable of processing 500,000+ credential pairs per hour across distributed infrastructure. Their proxy network consists of 40,000+ residential IPs obtained through a mix of legitimate proxy services and compromised IoT devices. They employ CAPTCHA-solving services (both ML-based and human farm) to bypass bot mitigation controls.
Motivation: Financial — loyalty points are treated as a liquid currency. Compromised accounts with high point balances are sold on dark web marketplaces at 60–70% of face value. Points are laundered through gift card purchases, merchandise orders shipped to drop addresses, and transfer to mule accounts.
Public Research Context
This scenario is informed by publicly documented credential stuffing campaigns:
- 2018–2020 airline loyalty breaches: Multiple major airlines reported mass account takeover of frequent flyer programs — attackers liquidated millions of miles via gift card redemptions
- Akamai State of the Internet Report (2022): 193 billion credential stuffing attacks observed globally — loyalty programs among the top 3 targeted verticals
- FBI IC3 Report: Account takeover losses exceeded $12.5 billion in 2023 — credential stuffing identified as primary attack vector
- OWASP Automated Threats: OAT-008 (Credential Stuffing) and OAT-007 (Credential Cracking) are top automated threats to web applications
All technical details in this scenario are synthetic. No real airline or loyalty program data is used.
Scenario Narrative¶
Phase 1 — Credential Acquisition & Infrastructure Setup (~30 min)¶
Velocity Airlines is a synthetic mid-size commercial airline operating a loyalty rewards program called VelocityRewards with 12 million members. Members accumulate points through flights, credit card spending, and partner purchases. Points can be redeemed for flights, seat upgrades, gift cards, and merchandise through the VelocityRewards web portal (rewards.velocityairlines.example.com).
HYDRA SWARM acquires a credential database containing 85 million email/password pairs from a 2025 breach of an unrelated e-commerce platform. The group processes the database through their custom deduplication and formatting pipeline, producing a refined list of 42 million unique credential pairs. Based on historical success rates (0.5–2.0% match rate against airline loyalty programs), they estimate 210,000–840,000 valid account compromises.
The group provisions their attack infrastructure:
- Proxy infrastructure: 40,000 residential IPs across 28 countries, rotated every 3–5 requests per IP
- CAPTCHA solving: Contract with a human CAPTCHA farm (avg. solve time: 8 seconds, cost: $2.50/1000 solves) and an ML-based CAPTCHA solver for reCAPTCHA v2 (70% success rate)
- Credential testing framework: Custom Python tool (
hydra-stuffer) with configurable request templates, rate limiting, session management, and result classification - Command and control: Coordination via encrypted messaging; results aggregated to a PostgreSQL database hosted at
203.0.113.50
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| Dark Web Intelligence | Credential database listing on "BreachBazaar" marketplace — 85M records — Source: "ShopEZ breach 2025" — Price: 0.15 BTC — Seller reputation: 4.8/5 — 2026-01-10 |
| Dark Web Intelligence | HYDRA SWARM operational posting: "Looking for airline loyalty site configs — paying $500 per working config" — 2026-01-12 |
| Proxy Provider Logs | Account swarm_ops_28@proton.example — 40,000 residential IPs provisioned — Billing: cryptocurrency — 2026-01-14 |
| CAPTCHA Farm | Contract activated: 500,000 solve quota — Client ID: HS-2026-0118 — 2026-01-15 |
Phase 1 — Discussion Inject
Technical: The threat actor acquired 85 million credentials from a breach of an unrelated platform. What is the expected credential reuse rate for airline loyalty programs? How does password reuse behavior vary across demographics and account types?
Decision: Velocity Airlines has no dark web monitoring program. A threat intelligence vendor offered to provide breach monitoring for $45,000/year. The CISO declined, citing budget constraints. In hindsight, what ROI calculation should have been presented to justify this investment?
Expected Analyst Actions: - [ ] Assess whether breach monitoring or credential exposure services would have provided early warning - [ ] Review the organization's password policy — does it enforce uniqueness or check against known breached passwords? - [ ] Evaluate whether the VelocityRewards portal enforces MFA for login or high-value redemptions - [ ] Determine if the organization subscribes to Have I Been Pwned domain search or similar services
Phase 2 — Automated Credential Testing (~35 min)¶
On 2026-01-18, HYDRA SWARM launches the credential stuffing campaign against rewards.velocityairlines.example.com/api/v2/auth/login. The attack runs continuously for 72 hours.
The login API accepts JSON POST requests:
HYDRA SWARM's attack framework operates with the following parameters:
- Request rate: 150 requests/second (distributed across 40,000 IPs — avg. 0.00375 req/s per IP)
- Session rotation: New TLS session per IP rotation — randomized User-Agent strings from a pool of 2,000 browser fingerprints
- CAPTCHA handling: Pre-solved tokens injected into requests — average token lifetime: 120 seconds
- Error handling: Automatic retry on HTTP 429 (rate limited) with exponential backoff; skip on HTTP 403 (IP blocked)
- Result classification: HTTP 200 + valid session cookie = success; HTTP 401 = invalid credentials; HTTP 403 = account locked
Over the 72-hour campaign:
| Metric | Value |
|---|---|
| Total login attempts | 38,880,000 |
| Unique credential pairs tested | 32,400,000 |
| Successful logins (valid credentials) | 287,400 (0.89% match rate) |
| Accounts with point balance > 50,000 | 43,100 |
| Accounts with point balance > 200,000 | 8,720 |
| CAPTCHA solves consumed | 412,000 |
| Unique IPs used | 38,200 |
| IPs blocked by WAF | 1,240 (3.2%) |
| HTTP 429 rate limit responses | 89,000 |
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| WAF Logs (Cloudflare) | Login endpoint: 38.8M requests over 72h — 38,200 unique source IPs — Geographic distribution: 28 countries — Top countries: US (32%), BR (18%), IN (12%) — 2026-01-18T00:00:00Z to 2026-01-21T00:00:00Z |
| Application Logs | Failed login rate: 99.11% (vs. baseline of 15–20%) — Success rate: 0.89% — Average response time degraded from 120ms to 890ms — 2026-01-18 to 2026-01-21 |
| WAF Logs | Rate limiting triggered: 89,000 HTTP 429 responses — But rate limit rule was per-IP (100 req/10 min) — attacker's per-IP rate was 0.2 req/10 min — rate limit never effectively triggered |
| Bot Management | JavaScript challenge pass rate: 94% (legitimate users: 99.8%) — Anomaly: 6% of sessions failed JS challenge but passed CAPTCHA — indicative of headless browser with external CAPTCHA solving |
| Network Flow | No single IP exceeded 50 requests in any 10-minute window — traffic appeared organic from an IP-frequency perspective |
Phase 2 — Discussion Inject
Technical: The WAF rate limit is configured per-IP at 100 requests per 10 minutes. The attacker's per-IP rate is 0.2 requests per 10 minutes. What alternative rate limiting strategies would detect this distributed attack? Consider: per-account rate limiting, global login failure rate monitoring, device fingerprinting, and behavioral analysis.
Decision: Application response times have degraded from 120ms to 890ms during the attack. The NOC has noticed but attributes it to "increased traffic." Should the SOC proactively monitor application performance metrics as a security signal? What threshold would trigger an investigation?
Expected Analyst Actions: - [ ] Analyze login failure rate — 99.11% failure rate is a clear indicator of credential stuffing - [ ] Correlate geographic distribution of login attempts with normal user demographics - [ ] Examine CAPTCHA solving patterns — pre-solved tokens with consistent timing indicate automation - [ ] Review User-Agent diversity — 2,000 unique User-Agents from a single campaign is anomalous - [ ] Implement emergency rate limiting on the login endpoint based on global failure rate
Phase 3 — Account Takeover & Point Liquidation (~30 min)¶
After validating 287,400 accounts, HYDRA SWARM begins the monetization phase. The group prioritizes the 8,720 accounts with balances exceeding 200,000 points (each worth approximately $2,000 in redemption value).
The monetization workflow:
- Account lockout of legitimate owner: Change the account email to a HYDRA SWARM-controlled address (
<random>@mailhub.example.com), change the password, and remove any recovery phone numbers - Point redemption: Redeem points for digital gift cards (Amazon, Apple, Visa prepaid) — maximum 500,000 points per transaction
- Gift card laundering: Resell gift cards through secondary marketplaces at 70–80% face value
- Account cleanup: Delete redemption confirmation emails from the compromised account
Velocity Airlines does not require:
- MFA for login
- Re-authentication for email address changes
- Re-authentication for point redemptions
- Email notification to the original address when the account email is changed
- Cooldown period after email/password changes before high-value transactions
Evidence Artifacts:
| Artifact | Detail |
|---|---|
| Application Logs | Email change events: 8,720 accounts — All changed to *@mailhub.example.com domain — Time window: 2026-01-21T06:00:00Z to 2026-01-22T18:00:00Z |
| Application Logs | Password change events: 8,720 accounts — Immediately following email changes — Same session IDs as email changes |
| Redemption System | Gift card redemptions: 14,200 transactions — Total points redeemed: 3.48 billion — Estimated value: $34.8 million — 2026-01-21 to 2026-01-25 |
| Customer Support | Call volume spike: 340% increase — Primary complaint: "locked out of account" and "points missing" — 2026-01-23 onward |
| Customer Support | First escalation to security team: 2026-01-24T14:30:00Z — 6 days after attack began, 3 days after account takeovers started |
2026-01-21 06:00 — Email changes begin (8,720 accounts)
2026-01-21 08:00 — Password changes complete
2026-01-21 12:00 — First gift card redemptions
2026-01-25 23:59 — Last gift card redemption
2026-01-23 09:00 — First customer complaints to call center
2026-01-24 14:30 — Call center escalates to security team
2026-01-24 16:00 — Security team begins investigation
2026-01-24 18:00 — Emergency: freeze all gift card redemptions
Phase 3 — Discussion Inject
Technical: The attacker changed 8,720 account email addresses to a single domain (mailhub.example.com). What detection rule would flag a surge in email changes to a single domain? What about changes to free email providers (Gmail, Outlook, ProtonMail)?
Decision: It took 6 days from the start of the attack and 3 days from the start of account takeovers before security was notified. Customer support received hundreds of "locked out" calls but did not have a process to escalate security-relevant patterns. How do you build a feedback loop between customer support and the SOC?
Expected Analyst Actions: - [ ] Immediately freeze all gift card redemptions and account changes - [ ] Identify all accounts with email changes in the attack window - [ ] Reverse unauthorized email/password changes and restore original owner access - [ ] Correlate account takeover sessions with the credential stuffing IPs from Phase 2 - [ ] Calculate total financial exposure and initiate the fraud investigation process - [ ] Notify affected customers and force password resets
Detection & Hunting¶
KQL Detection Queries¶
// Detect credential stuffing — high login failure rate on a single endpoint
SigninLogs
| where TimeGenerated > ago(1h)
| where AppDisplayName == "VelocityRewards Portal"
| summarize TotalAttempts = count(),
FailedAttempts = countif(ResultType != "0"),
SuccessAttempts = countif(ResultType == "0"),
UniqueIPs = dcount(IPAddress),
UniqueAccounts = dcount(UserPrincipalName)
by bin(TimeGenerated, 10m)
| extend FailureRate = round(FailedAttempts * 100.0 / TotalAttempts, 2)
| where FailureRate > 80 and TotalAttempts > 1000
| project TimeGenerated, TotalAttempts, FailedAttempts, FailureRate, UniqueIPs, UniqueAccounts
// Detect mass email changes to a single domain
AuditLogs
| where TimeGenerated > ago(24h)
| where OperationName == "Update user"
| where TargetResources has "email"
| extend NewEmail = tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[0].newValue)
| extend NewDomain = tostring(split(NewEmail, "@")[1])
| summarize AccountsChanged = count(), Accounts = make_set(TargetResources[0].userPrincipalName) by NewDomain
| where AccountsChanged > 10
| sort by AccountsChanged desc
// Detect distributed credential stuffing — low per-IP but high aggregate
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType != "0"
| summarize AttemptsPerIP = count() by IPAddress
| where AttemptsPerIP between (1 .. 50)
| summarize SuspiciousIPs = count(), TotalAttempts = sum(AttemptsPerIP)
| where SuspiciousIPs > 500 and TotalAttempts > 10000
SPL Detection Queries¶
// Detect credential stuffing via login failure spike
index=web sourcetype=access_combined uri_path="/api/v2/auth/login" method=POST
| bin _time span=10m
| stats count as total_attempts,
count(eval(status=401)) as failed,
count(eval(status=200)) as success,
dc(clientip) as unique_ips,
dc(form_username) as unique_accounts by _time
| eval failure_rate = round((failed/total_attempts)*100, 2)
| where failure_rate > 80 AND total_attempts > 1000
| table _time, total_attempts, failed, failure_rate, unique_ips, unique_accounts
// Detect gift card redemption anomaly
index=application sourcetype=rewards_transactions action=redeem product_type=gift_card
| bin _time span=1h
| stats count as redemptions, sum(point_value) as total_points, dc(account_id) as unique_accounts by _time
| eventstats avg(redemptions) as avg_redemptions, stdev(redemptions) as stdev_redemptions
| eval z_score = (redemptions - avg_redemptions) / stdev_redemptions
| where z_score > 3
| table _time, redemptions, total_points, unique_accounts, z_score
// Detect distributed login attempts below per-IP rate limits
index=web sourcetype=access_combined uri_path="/api/v2/auth/login" status=401
| stats count as attempts by clientip
| where attempts >= 1 AND attempts <= 50
| stats count as suspicious_ips, sum(attempts) as total_attempts
| where suspicious_ips > 500 AND total_attempts > 10000
Indicators of Compromise (IOCs)¶
Synthetic IOCs — For Training Only
All indicators below are synthetic and generated for educational purposes. Do not use in production detection systems.
| Type | Indicator | Context |
|---|---|---|
| IP Address | 203.0.113.50 | C2 / results aggregation server |
| IP Range | 198.51.100.0/24 | Proxy management infrastructure |
| Domain | mailhub.example.com | Attacker-controlled email domain for account takeovers |
| Domain | rewards.velocityairlines.example.com | Target application (synthetic) |
| Email Pattern | *@mailhub.example.com | All ATO email changes pointed to this domain |
| User-Agent | Pool of 2,000 randomized browser fingerprints | Automated credential testing framework |
| API Endpoint | /api/v2/auth/login | Targeted login endpoint |
| Behavior | >80% login failure rate over 10-minute window | Credential stuffing indicator |
| Behavior | >10 email changes to single domain in 24h | Mass account takeover indicator |
| Behavior | Gift card redemption volume >3x baseline | Loyalty point liquidation indicator |
Full Attack Timeline¶
| Time | Event | ATT&CK ID |
|---|---|---|
| 2026-01-10 | HYDRA SWARM acquires 85M credential database from dark web | T1589.001 |
| 2026-01-12 | Attack infrastructure provisioning begins | T1583.003 |
| 2026-01-14 | Residential proxy network activated (40,000 IPs) | T1583.003 |
| 2026-01-15 | CAPTCHA solving contract activated | T1583.003 |
| 2026-01-18 00:00 | Credential stuffing campaign begins | T1110.004 |
| 2026-01-21 00:00 | Credential stuffing campaign ends — 287,400 valid accounts identified | T1110.004 |
| 2026-01-21 06:00 | Account takeover begins — email/password changes on 8,720 high-value accounts | T1531 |
| 2026-01-21 12:00 | Gift card redemptions begin — loyalty point liquidation | T1078.004 |
| 2026-01-23 09:00 | First customer complaints — "locked out of account" | — |
| 2026-01-24 14:30 | Customer support escalates to security team | — |
| 2026-01-24 16:00 | Security investigation begins | — |
| 2026-01-24 18:00 | Emergency freeze on all gift card redemptions | — |
| 2026-01-25 | Incident response: full scope assessment, customer notification begins | — |
Lessons Learned¶
Critical Failures¶
-
No MFA on loyalty accounts: The VelocityRewards portal relied solely on email/password authentication. MFA would have rendered 99%+ of credential stuffing attempts useless, even with valid credentials.
-
Per-IP rate limiting is insufficient: The WAF rate limit (100 req/10 min per IP) was trivially bypassed by distributing requests across 40,000 residential IPs. Effective defense requires per-account rate limiting, global failure rate monitoring, and behavioral analysis.
-
No re-authentication for high-risk actions: Email changes, password changes, and point redemptions required no re-authentication or step-up verification. An attacker with valid credentials could fully take over and monetize an account in a single session.
-
No customer support-to-SOC feedback loop: Hundreds of "locked out" complaints arrived 2 days before security was notified. Customer support had no process to escalate security-relevant patterns.
-
No breach credential monitoring: Velocity Airlines did not monitor for employee or customer credentials appearing in breach databases. Early detection of the ShopEZ breach data could have triggered proactive password resets.
Recommended Controls¶
| Control | Priority | ATT&CK Mitigation |
|---|---|---|
| Enforce MFA for all loyalty accounts (TOTP, WebAuthn, or SMS) | Critical | M1032 |
| Implement per-account login rate limiting (5 failures/15 min) | Critical | M1036 |
| Require re-authentication for email change, password change, and redemptions > 50,000 points | Critical | M1032 |
| Deploy advanced bot management (device fingerprinting, behavioral analysis) | High | M1036 |
| Monitor global login failure rate — alert when failure rate exceeds 50% | High | M1031 |
| Implement breached credential checking (HIBP API, Enzoic, or equivalent) at login | High | M1027 |
| Build automated escalation from customer support ticket patterns to SOC | Medium | M1031 |
| Deploy CAPTCHA with proof-of-work challenge (not solvable by human farms) | Medium | M1036 |
| Implement login anomaly detection: new device + new location + email change = high risk | Medium | M1018 |
| Add cooldown period (24h) between email/password change and high-value redemptions | Medium | M1032 |
Cross-References¶
- Chapter 33: Identity Chapter 11: Identity & Access Management Access Security](../chapters/ch33-identity-access-security.md) — MFA, credential management, and authentication controls
- Chapter 30: Application Security — Bot management, rate limiting, and application-layer defenses
- Chapter 30: Application Security — Business logic security, API abuse prevention, and secure authentication design