The Capital One Breach: SSRF, Metadata Credentials, 100 Million Records
How the 2019 Capital One breach worked: a server-side request forgery against a misconfigured WAF, the EC2 metadata service handing over role credentials, and an S3 role that could read far more than it needed.
The Capital One breach is the case that taught a generation of cloud engineers what the metadata service is.
The chain has four links and no exotic step. A web application firewall running on an EC2 instance could be induced to make requests to arbitrary destinations. One of those destinations was the instance metadata service. The metadata service returned credentials for the IAM role attached to the instance. That role could read a great deal of S3.
Nothing was exploited in the sense of a memory corruption or a novel technique. Each component did what it was built to do, and the combination produced the theft of records on roughly 100 million people.
Scope: SSRF Explained owns the application weakness and how to prevent it, and Cloud Misconfigurations owns the settings, including the metadata service configuration. This page owns the incident and the sequence.
Timeline
| Date | Event |
|---|---|
| March 2019 | Unauthorised access occurs |
| 17 July 2019 | An external tip alerts Capital One that data appears to have been posted publicly |
| 19 July 2019 | The company confirms the intrusion |
| 29 July 2019 | Public disclosure. Approximately 100 million US and 6 million Canadian applicants affected |
| August 2020 | The OCC assesses an 80 million dollar civil money penalty |
| December 2021 | A 190 million dollar class action settlement is agreed, with liability denied |
The detection detail is worth noting on its own: the company learned of the breach from an outside report four months after the access, rather than from its own monitoring.
The chain
Link one: a request-forgery weakness in a security product. The vulnerable component was a web application firewall, misconfigured in a way that allowed an attacker to cause it to issue requests to a destination they chose. It is worth pausing on the irony, and more usefully on the general point: a WAF is software running on a host. It parses untrusted input for a living. It can have vulnerabilities and it can be misconfigured, exactly like the applications it protects.
Link two: the metadata service answered. Every EC2 instance can query 169.254.169.254 for information about itself. Under IMDSv1 that is a plain HTTP GET with no headers required, and one of the paths returns temporary credentials for the IAM role attached to the instance:
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
The response is JSON containing an access key, a secret key and a session token. The application had no business talking to the metadata service and did not need to; it only needed to fetch a URL somebody else chose.
Link three: the role had broad permissions. The credentials belonged to the role attached to the instance, and that role could list and read S3 buckets well beyond what the component required for its function. This is the link that turned an interesting bug into a large breach. An SSRF that yields credentials to a role with no useful permissions is a finding; the same bug yielding credentials to a role that can read the customer data estate is an incident.
Link four: bulk retrieval. With valid credentials, listing and downloading objects is ordinary API usage. Nothing malformed, nothing exploited, no alarm inherent in the requests themselves.
Why nothing alerted
Each request in the chain was legitimate in isolation.
The metadata request came from the instance, which is the only place it can come from. The S3 calls carried valid credentials and appropriate permissions. There was no malware, no unusual process, no exploit signature. Endpoint tooling on the instance had nothing anomalous to see, because from the operating system's perspective a normal process made normal outbound requests.
What was visible, in principle, was the shape of the activity in cloud audit logs: an instance role that normally performs a narrow set of operations suddenly performing large numbers of list and get calls across many buckets. That is a detection worth building, and it belongs to the same family as the KMS decrypt-volume detection in Cloud Key Management Explained. Volume and pattern anomalies on authorised API calls are frequently the only signal available when the credentials are real.
What the regulator actually said
The OCC's penalty language is more useful than the technical narrative for anyone planning a cloud migration. The finding was that the bank failed to establish effective risk assessment processes before migrating significant information technology operations to the public cloud, and failed to correct identified deficiencies in a timely manner.
That is not a statement about one misconfigured firewall. It is a statement about governance: moving material operations into a different architecture, with a different security model and different failure modes, and not building the assessment and control processes to match it beforehand.
For anyone in a regulated sector, this is the sentence to take away. The regulator did not need to understand SSRF to find fault, and the finding would have stood even if the specific bug had been different.
The controls, stated plainly
Everything on this list is available today and most of it is a single setting.
Enforce IMDSv2, and set the hop limit to 1. Version 2 requires a PUT to obtain a session token and a header on subsequent requests, which most request-forgery primitives cannot produce. The hop limit stops the response surviving a hop to a container on a bridged network. Both can be set as an account-level default so new instances inherit them.
Scope instance roles to the workload. The permissions on the role attached to a host are the ceiling on what any bug on that host can reach. A component that needs one bucket should have one bucket, per Least Privilege Explained.
Treat SSRF as a high-severity class in cloud environments, not a medium. Allowlist outbound destinations where the application makes server-side requests, block the link-local range from application egress, and validate after DNS resolution rather than on the string. SSRF Explained has the detail.
Monitor cloud API activity for volume anomalies by instance roles, since the credentials will be valid and the calls will be authorised.
Do the risk assessment before the migration, which is the thing the regulator actually penalised.
What generalises
- An instance role is the blast radius of every flaw on the instance. Size it accordingly.
- Security products are software, with vulnerabilities and misconfigurations of their own.
- Metadata services are a credential vending machine reachable from inside the host. Every major cloud has one, and each has a hardening mode that should be mandatory.
- When the credentials are real, only behaviour is anomalous. Build detections on volume and pattern in the audit log.
- Governance is assessed separately from the bug. Regulators ask what process existed before the migration.
The verdict
Four links, none of them clever, ending in the records of a hundred million people. The bug was ordinary, the metadata service worked as specified, the role was too broad, and detection came from an outside tip four months later.
The two settings that break this chain, IMDSv2 enforced and a tightly scoped instance role, take an afternoon across an entire account. That combination is the whole lesson, and it is worth checking rather than assuming, because the accounts most likely to still be on version 1 are the ones created before anyone had heard of this incident.
Related guides
Sources & further reading
- OCC Assesses $80 Million Civil Money Penalty Against Capital One (US Office of the Comptroller of the Currency)
- Information on the 2019 Capital One Cyber Incident (Capital One)
- Use IMDSv2 (Amazon Web Services)
- AWS Shared Responsibility Model (Amazon Web Services)
- OWASP Server Side Request Forgery Prevention Cheat Sheet (OWASP)