On July 19, 2019, Capital One disclosed that a former Amazon Web Services employee named Paige Thompson had accessed roughly 106 million customer records — about 100 million in the United States and 6 million in Canada — by exploiting a misconfigured web application firewall in front of a Capital One application hosted on AWS. The WAF had excessive IAM permissions and was vulnerable to server-side request forgery (SSRF), letting Thompson trick it into querying the EC2 instance metadata service and hand back temporary IAM credentials for a role with access to more than 700 S3 buckets. Those buckets held Social Security numbers, bank account numbers, and credit scores. Two years earlier, in 2017, security researcher Chris Vickery at UpGuard found four Accenture-owned S3 buckets sitting wide open to the public internet, including a 137GB bucket of database backups with plaintext API keys and roughly 40,000 plaintext passwords. Both incidents trace back to specific, well-documented AWS misconfigurations — not zero-days — and both map cleanly to controls that exist today. This post walks through what actually happened in each case and the exact setting, service, or scanning pattern that would have closed the gap.
What exactly let Capital One's attacker steal IAM credentials?
The root cause was AWS's original Instance Metadata Service (IMDSv1), which answered any HTTP request from inside an EC2 instance — including one relayed through a vulnerable proxy — with no authentication token required. Thompson's SSRF payload forced the misconfigured WAF to make a request to http://169.254.169.254/latest/meta-data/iam/security-credentials/ on Capital One's behalf, and the metadata service handed back temporary credentials for the IAM role attached to that instance, no questions asked. Those credentials turned out to be scoped far too broadly, letting a single compromised proxy reach S3 buckets well outside its actual job. AWS's fix, IMDSv2, requires a session token obtained via a PUT request before any metadata GET succeeds — a change that blocks basic SSRF-to-credential-theft because a simple forwarded GET request can no longer retrieve anything. IMDSv2 became available in November 2019 and AWS began defaulting new EC2 launches to it, and later announced it would make IMDSv2 the default for new instances. Paired with least-privilege IAM scoping — so a WAF's role can reach the handful of buckets it actually needs — this closes both the entry point and the blast radius in one move.
What made the Accenture S3 exposure possible, and did AWS change anything because of it?
The Accenture exposure, disclosed by UpGuard's Chris Vickery in September 2017, came down to bucket-level access control lists set to allow public read access on four buckets — nicknamed "acp-deployment," "acpcollector," "acp-software," and "acp-ssl" in Accenture's own naming. Inside sat plaintext AWS KMS master keys, API keys, and credentials for Accenture's internal Cloud Platform product, the kind of access that could have let an attacker impersonate Accenture's infrastructure to its own clients. There was no breach of an application or exploit chain involved — someone simply set the ACL to public and nobody caught it before Vickery did. AWS's S3 Block Public Access, an account- and bucket-level setting that overrides any ACL or policy attempting to grant public access, shipped in November 2018, after a string of similar S3 exposures (including Accenture's) had become a recurring news cycle. Turning it on account-wide, plus a CI check that lints bucket policies before they're applied, would have stopped this specific class of exposure outright rather than relying on someone noticing an open bucket.
Why do S3 misconfigurations keep recurring across unrelated companies?
Public S3 buckets are not a one-off failure mode — they are a pattern that has repeated across companies with no relationship to each other beyond using the same default settings. Researchers and journalists have documented exposed AWS buckets tied to Verizon's call-center partner Nice Systems, WWE, Dow Jones, and Pegasus Airlines, among others, generally with the same two ingredients: a bucket ACL or policy left at public-read, and no monitoring in place to catch the drift once it happened. What differs case to case is the payload — customer PII in one, call-center recordings in another, marketing lead lists in a third — but the mechanism doesn't change: someone (or some deploy script) sets a permissive policy, and nothing downstream flags it as public before an outsider finds it, often a security researcher running an internet-wide bucket-name scanner rather than a targeted attacker. That repetition is why the fix has converged industry-wide on continuous, automated public-exposure scanning of every bucket, rather than a one-time manual audit at launch, because the failure is rarely deliberate and rarely caught by intent alone.
What's the practical difference between a WAF/IAM failure and a data-exposure failure?
Capital One and Accenture look similar from a headline distance — "AWS breach" — but they sit in different parts of the control stack, and conflating them leads teams to buy the wrong tooling. Capital One's failure was a network- and identity-layer problem: an internet-facing application had a code-level vulnerability (SSRF) combined with an overly permissive IAM role and an unprotected metadata endpoint, so the fix lives in IMDSv2, WAF hardening, and IAM least-privilege — not in scanning stored data. Accenture's failure was a data-layer and configuration problem: nobody exploited an application at all, they found data that was already sitting in the open, so the fix lives in bucket-policy enforcement and continuous exposure detection. A security program that only runs SAST and dependency scanning would have caught neither: Capital One needed infrastructure and identity controls, Accenture needed a system that continuously classifies what's stored in cloud data stores and flags when access to it is public or over-shared. Treating "AWS security" as one bucket of controls instead of at least these two distinct layers is itself a common root cause of gaps.
How Safeguard Helps
Safeguard's DSPM connects directly to S3 and RDS to classify what's actually stored in a bucket or table — PII, PHI, payment data, and secrets — and records each store's encryption status and public exposure (bucket ACLs, public-access settings, and bucket policy) as first-class posture signals. That's the Accenture failure mode by name: DSPM fuses that classification with CIEM effective-permissions data to flag exactly when a sensitive store is reachable by too many identities or by anyone outside your tenant boundary, and a public, unencrypted store holding classified PII is scored and surfaced well before a researcher like Chris Vickery finds it first. Separately, Safeguard's secrets scanning verifies any AWS keys it finds in code, containers, or Git history with a live sts:GetCallerIdentity call, so a credential leaked into a repository or a build log is confirmed as live-and-exploitable rather than left as a theoretical match, with revoke and rotate playbooks to close it out. Safeguard doesn't claim to replace IMDSv2 or WAF-layer SSRF protections — that's an infrastructure and network control, not a scanning one — but for the data-exposure and credential-exposure failure modes behind Accenture and the broader pattern of public-bucket incidents, continuous classification and verified secrets detection are exactly the controls that close the gap.