Capital One, a big US credit card bank, ran part of its services on rented cloud servers. On 17 July 2019, a stranger emailed the inbox it keeps for people reporting security holes: "There appears to be some leaked s3 data of yours in someone's github / gist."
The file on GitHub, timestamped 21 April 2019, held the address of one Capital One server, code for three commands and a list of more than 700 folders, or "buckets", of Capital One data. A firewall misconfiguration let commands reach that server and run on it, says the criminal complaint.
- The first command obtained security credentials for an account called
*****-WAF-Role. - The second used that account to list the buckets in Capital One's cloud storage.
- The third copied data out of the buckets the account had permission to read.
Capital One tested the commands. They worked. Its logs showed the account listing buckets on or about 22 March 2019, from addresses the FBI agent believed to be Tor exit nodes, which hide where traffic comes from. In the ordinary course of business, that account never listed buckets at all. The same day, it copied data, including credit card application files, some of it through a VPN service.
On 19 July, Capital One determined that an outsider had got in, and began working with federal law enforcement. The FBI caught the person; the criminal complaint was filed on 29 July. By Capital One's count, the data covered about 100 million people in the US and about 6 million in Canada, including about 140,000 US Social Security numbers. No credit card account numbers or login credentials were taken.
In August 2020, the OCC, a US bank regulator, fined Capital One $80 million for failing to set up effective risk assessment before moving significant IT operations to the public cloud.
- 3 commands and a list of more than 700 buckets
- About 100 million people in the US and 6 million in Canada
- About 140,000 US Social Security numbers
- $80 million OCC penalty
Why it matters: In the cloud, a server's identity is a key: whoever can make it run commands gets everything its role can reach. Give each role only what it needs, and alert when it acts out of character.