INFRA-CAPITALONE-2019
Cloud · AWS · AWS EC2 / S3 (misconfigured WAF and IAM role)
Summary
A misconfigured ModSecurity web application firewall on an AWS EC2 instance was abused via server-side request forgery to reach the EC2 Instance Metadata Service at 169.254.169.254 and retrieve the temporary IAM credentials of the WAF's role. Because that role was over-privileged, the attacker used the stolen credentials to exfiltrate data from Capital One's S3 buckets. Roughly 100 million US individuals and 6 million Canadians were exposed, including about 140,000 Social Security numbers and 80,000 linked bank account numbers. Attacker Paige Thompson, a former AWS engineer, was arrested July 29, 2019 and later convicted. The incident directly motivated AWS's release of IMDSv2.
How to avoid it in your code
- Enforce IMDSv2 (require session tokens, set the hop limit to 1) so an SSRF cannot read instance role credentials.
- Scope EC2 instance IAM roles to least privilege; never grant broad S3 list/get across all buckets.
- Block SSRF at the app and egress layers: validate/allowlist outbound URLs and deny access to 169.254.169.254.
- Enable S3 Block Public Access and encrypt sensitive data; alert on large or unusual S3 reads.
- Monitor CloudTrail/GuardDuty for instance credentials used from outside the instance or for anomalous API calls.
References
- https://krebsonsecurity.com/2019/08/what-we-can-learn-from-the-capital-one-hack/
- https://www.sec.gov/Archives/edgar/data/0000927628/000092762819000262/exhibit991-pressrelease72919.htm
- https://www.justice.gov/usao-wdwa/pr/seattle-tech-worker-arrested-data-theft-involving-large-financial-services-company
Related vulnerabilities
All Infra →- HIGHCONTAINER-LEAKY-VESSELS-2024
Leaky Vessels was a set of container-escape vulnerabilities disclosed on 31 January 2024 by Rory McNamara of Snyk Security Labs, the headline flaw being CVE-2024-21626 (CVSS 8.6, runc 1.1.11 and earlier). It was an order-of-operations file-descriptor leak in runc's handling of the process working directory (WORKDIR / process.cwd). During container setup runc left an internal file descriptor referencing the host filesystem namespace open before all privileged descriptors were closed, so a malicious image or a build using a malicious Dockerfile or upstream FROM could set the working directory to that leaked descriptor via a path like /proc/self/fd/7. Because chdir occurred before the descriptor was closed, the container process gained a working directory in the host filesystem and could read and write host files, breaking container isolation and escaping to the underlying host. Related Docker BuildKit issues were disclosed alongside it: CVE-2024-23651 (mount cache race), CVE-2024-23652 (build-time arbitrary delete), and CVE-2024-23653 (GRPC SecurityMode privilege check bypass). The flaw was fixed in runc 1.1.12.
- HIGHCLOUD-CLOUDSQL-PRIVESC-2023
On 24 May 2023 Dig Security disclosed a privilege-escalation chain in Google Cloud SQL for SQL Server, originally reported to Google in February 2023, that let an attacker escalate from a limited database role to full system administrator and reach the host operating system. The chain first abused a gap in GCP's security hardening to add the attacker's user to DbRootRole, an elevated GCP admin role that nonetheless lacked full SQL Server permissions, then exploited a further misconfiguration in the role permission architecture to grant the SQL Server sysadmin role and obtain complete control of the database engine. With sysadmin rights the researchers reached the underlying container and host OS, letting them list privileged paths, read sensitive files and extract secrets, including internal GCP data and credentials related to the managed service. This was a provider-side flaw under shared responsibility that customers could not patch; Google remediated it in April 2023 and it was found and reported by researchers with no evidence of exploitation in the wild.
- MEDIUMCLOUD-TOYOTA-2023
On May 12, 2023, Toyota disclosed that a cloud environment managed by its Toyota Connected subsidiary had exposed data on roughly 2.15 million customers, essentially the entire Japanese user base of its T-Connect, G-Link, G-Link Lite, and G-BOOK connected services registered since November 2013. The data was exposed from November 6, 2013 to April 17, 2023, nearly a decade, and included in-vehicle GPS terminal IDs, vehicle chassis numbers, location history with timestamps, and a subset of drive-recorder video footage, but not names, credit cards, or other directly identifying personal data. The root cause was a cloud database misconfigured to be publicly accessible instead of private, attributed to human error during setup and allowing unauthenticated internet access. Toyota cited a lack of active detection mechanisms and insufficient enforcement of data-handling rules, which is why the misconfiguration persisted undetected for years. A follow-up disclosure on May 31, 2023 found additional misconfigured cloud services exposing around 260,000 more customers.
- HIGHCLOUD-BLUEBLEED-2022
On September 24, 2022 SOCRadar discovered a misconfigured Microsoft Azure Blob Storage endpoint that exposed roughly 2.4 TB of business data spanning 65,000+ entities across 111 countries, with files dated from 2017 to August 2022, though Microsoft disputed the entity count as exaggerated. The exposed data included customer names, email addresses, phone numbers, company names, and business transaction documents such as signed invoices, proof-of-execution and statement-of-work files, and product offers. The low-level misconfiguration was that the Blob Storage endpoint's access level was set to allow anonymous public access instead of requiring authentication, so the container and its blobs were readable over the internet without any credential. Microsoft's Security Response Center attributed it to an unintentional misconfiguration on an endpoint not in use and reconfigured it to require authentication, stating it found no indication that accounts or systems were compromised.
- CRITICALCLOUD-AZURESCAPE-2021
On 9 September 2021 Palo Alto Unit 42 researcher Yuval Avrahami disclosed Azurescape, described as the first cross-account container takeover in a public cloud, in which a malicious container on Azure Container Instances could escape and gain control over other customers' containers running on the shared multitenant Kubernetes cluster. ACI ran an outdated container runtime, runC v1.0.0-rc2, which was vulnerable to CVE-2019-5736, letting the attacker break out of the container and execute code as root on the underlying Kubernetes node. From the node the researcher found the bridge pod, which serviced az container exec calls, sent a Kubernetes service-account token in the Authorization header to a Kubelet that also allowed anonymous access; decoding that token (related to CVE-2018-1002102) granted pods/exec rights across all namespaces and control of the api-server, and thus the whole multitenant cluster. This was a provider-side flaw under shared responsibility that customers could not patch; Unit 42 found it and reported it with no knowledge of exploitation in the wild.
- HIGHCLOUD-POWERAPPS-2021
On August 23, 2021, UpGuard disclosed that misconfigured Microsoft Power Apps portals exposed roughly 38 million records across 47 organizations, including American Airlines, Ford, J.B. Hunt, the Maryland Department of Health, the State of Indiana, New York City agencies, and Microsoft itself. Exposed data included names, email addresses, phone numbers, social security numbers, and COVID-19 contact tracing and vaccination appointment information. Power Apps portals surface list data through OData list feeds reachable at predictable URLs, and access to those feeds is gated by Table Permissions, but Table Permissions were disabled by default on every list. Because security was opt-in, any portal where a developer enabled an OData feed without explicitly configuring and enabling Table Permissions returned its records to any unauthenticated visitor querying the OData endpoint. This is an insecure-default access-control misconfiguration where the platform defaulted to anonymous read rather than deny.