DEV Community

CAISD
CAISD

Posted on

SSRF to AWS Credential Harvest — The Capital One Attack Chain, Visualized| CAISD

No credentials. No malware. No special access.

Just a URL input — and a server with the wrong trust model.

This is how Capital One lost 100 million records in 2019.


What is SSRF?

Server-Side Request Forgery tricks your server into making HTTP requests on behalf of the attacker — including to internal metadata endpoints that should never be reachable from outside.


The Exact Attack Chain

Step 1 — Attacker sends a crafted request:

POST /api/document-import
url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-role"
Enter fullscreen mode Exit fullscreen mode

Step 2 — Server blindly fetches the URL
The app was designed to import documents from URLs. It never validated which URLs.

Step 3 — AWS metadata endpoint responds with live IAM credentials
Access key, secret key, session token — all returned in plaintext.

Step 4 — Attacker enumerates S3 buckets
Using the harvested credentials to authenticate against AWS directly.

Step 5 — 100M records exfiltrated
Credit applications, SSNs, bank account numbers.

Total time from exploit to data? Hours.


The Fix — 4 Layers of Defense

Layer What to do
Input validation URL allowlist + block private IP ranges (169.254.x.x, 10.x.x.x, 172.16.x.x)
IMDSv2 enforcement Set HttpTokens: required — prevents unauthenticated metadata access
Network controls Egress firewall + ACLs blocking metadata endpoint from app servers
IAM hygiene Least-privilege roles — even if credentials leak, blast radius is minimal

Bug Bounty Severity Reference

  • 🔴 SSRF → AWS metadata endpoint = P1 Critical
  • 🔴 IAM credential harvest = P1 Critical
  • 🟠 Internal service discovery via SSRF = P2 High

TL;DR

One unvalidated URL parameter → full AWS credential access → 100M records gone.

IMDSv2 + URL allowlisting would have stopped this cold.


Full visual breakdown by CAISD — Bamdad Shahabi:


Tags to add on dev.to: security aws webdev tutorial

Top comments (0)