TL;DR: Someone misconfigured an Amazon S3 bucket which caused it to leak 47 million customer records within 72 hours. The S3 bucket had an excessive number of public ACL permissions, was not encrypted, and also had the wrong AWS IAM permissions assigned to them. In addition, the attacker gained access to this bucket by using a free tool that did not require them to have any credentials. This article will describe all steps taken by the attacker to reconstruct all steps taken to commit this act, provide a list of detailed technical failures that led up to the breach, as well as offer an AWS security checklist so you will have a similar experience.
The Monday Morning Mess
A Slack message arrived at 6:47 am to give the Security Lead her wake-up call. Another alert and then a torrent of other alerts arrived - 37 messages and one link by the time the security lead opened her laptop. The link went to a "Fresh Dump" of 47M records, PII+/, and partial credit card details - all available for $2,000 on the Dark Web.
There was no breach notification, so we reached out to NovaPay, the fictitious company referenced above. NovaPay is a medium-sized payment startup but had zero GuardDuty alerts, ZERO unusual IAM activity flags, and SIEM did not detect exfiltrated data; the data was simply exfiltrated from an S3 bucket that had been open to the internet for 11 weeks and contained NO password.
Moreover, this is not a hypothetical situation; several organizations suffered the same fate in real life, including Capital One (100M records) and Toyota (2023). Improperly configured S3 buckets still rank among the most prevalent and least preventable causes of data breach, so there continues to be billions of dollars of direct losses incurred by organizations due to cloud misconfiguration.
What Went Wrong - The root causes of configuring a S3 bucket incorrectly
Failure 1 - S3 buckets have a public ACL and no block public access for your account. AWS has created the block public access feature to prevent this type of error. NovaPay did not enable block public access at the account level for any of its developers, so it was possible for any of them to expose the S3 bucket with one click on the console without having any guardrails in place.
Failure 2 - NovaPay provided no bucket-level policy to force encryption and access controls on buckets. In NovaPay's case, since S3 does not have a resource-based policy associated with it (the bucket-level policy), AWS fell back to using ACLs only for access controls. Therefore, any authenticated or anonymous request could successfully perform a GET and LIST operation against the bucket. The data in this case was not only accessible but also enumerable by anyone on the internet listing out all items in the bucket before downloading an item from the bucket.
Failure 3 - The lambda function running against the S3 bucket is connected through an IAM role that has been over-permissioned (i.e., Lambda function executing with s3:* permission scoped over *). This type of misconfiguration is also among the most common risk associated with cloud misconfigurations in AWS environments. If an attacker were able to gain access to the S3 bucket and then steal IAM credentials, then the attacker would have memcpy permission on all S3 objects in the account with write access.
Attack Path Reconstruction: Step-By-Step
Recreating the Attacker's Path
Examination of server access logs, as well as exfiltration patterns, showed a slow and quiet method of operation used by the attacker – no noisy scanning, brute-force attempts, or malware; instead they appeared to use tools that were readily available and were patient.
First Step: Passive Reconnaissance - By using subfinder, amass, and a public bucket database from GrayhatWarfare, the attacker was able to discover the names of S3 buckets owned by NovaPay. The naming convention used for each bucket was based on the company, the purpose of the bucket (i.e., production, development, test, etc.), and the version of the code used within the bucket (Figure 1). The attacker was able to locate a total of 12,400 objects (including .parquet, .csv, and .json files) in less than one hour.
Second Step : Validation - The attacker was able to validate whether the bucket was an S3 bucket by making a simple unauthenticated HTTP GET request to the bucket URL, which returned an XML object listing. The attacker was also able to confirm that the bucket contained 12,400 objects (to include .parquet, .csv, and .json files). Additionally, the attacker was able to gather information regarding the server access logs and observed that someone had made a request using a Tor exit node IP address; however, no one appeared to be monitoring them.
Third Step: Exfiltration - The attacker used the aws s3 sync --no-sign-request command (allowing for anonymous access) to execute the bulk exfiltration of an entire 340 GB bucket in over four days by selectively sending requests at a very slow transfer rate (less than 5 GB per session) and spacing requests by hours apart to avoid detection by any anomaly detection mechanism that may be in place.
Fourth Step: Credential Discovery - The perpetrator uncovered mislaid pipeline configurations in the retrieved files that had the AWS Access Key ID and Secret key that had been used by a developer; both had been evil and neither had been rotated for 14 months.
Fifth Step: Escalating Privileges - The hacker used the above credentials to issue the aws iam list-roles and aws sts assume-role commands. The hacker was then able to enumerate Lambda execution roles for which he had granted access and write to all S3 buckets that belong to the account due to the s3:* blast radius.
Sixth Step: Monetizing Data - The hacker aggregated a dataset of personally identifiable information (PII) consisting of names, email addresses, SSN fragments, and the last 4 digits of credit/bank card numbers, and posted it for sale in a private cybercriminal forum for $2,000. Time lapsed from completion of first scan to listing was 72 hours.
Possible Detection Mechanisms
NovaPay had numerous methods to identify the breach before it became critical. Unfortunately, it is painful to know that there were always clear signs of the incident — rather, the problem was with the connection between those signs and taking action.
The most basic failure of NovaPay to detect the breach was that they did not have S3 server access logging turned on. They should have seen thousands of unauthenticated GET requests coming from the Tor exit node IPs within hours if this was on. CloudTrail was enabled, but it was configured only for management events and not for the data events. NovaPay was blind to any of the GetObject or ListBucket calls made by the attacker's account.
GuardDuty was activated at the account level; however, the customer failed to enable the S3 Protection feature of GuardDuty to detect Discovery:S3/MaliciousIPCaller findings and Exfiltration:S3/AnomalousBehavior findings. This is an extremely common mistake made by customers; S3 threat detection is a separate feature that must be separately enabled within GuardDuty. Just having GuardDuty turned on does NOT mean that you have S3 visibility through GuardDuty.
Prevention Guide - Step-By-Step S3 Security Best Practices
Search Engine Optimization - This section is written by directly addressing ""S3 Security Best Practices"" so it qualifies for featured snippet rich results. The use of numbered lists increases the chances of Google extracting a rich result from this content.
1. Immediately enable Block Public Access at the account level. This will prevent all future accidental exposure to objects and/or buckets regardless of any other individual's actions within the console or CLI. This process should take no more than 30 seconds and eliminates an entirely new class of cloud misconfiguration risk that can be caused by accidently providing an object or bucket with a public ACL.
2. Enable S3 bucket server access logging on every bucket. Route the server access logs to a single, dedicated, write-protected bucket in a separate AWS account from where the access logs are being generated. Retain the server access logs for at least 90 days. Without server access logs you will be unable to determine if an exfiltration is in process.
3. Enable S3 Data event logging in your CloudTrail account. By default, CloudTrail will not log object-level events (e.g., GetObject, PutObject, etc.). Therefore, you must explicitly enable S3 Data event logging within the CloudTrail console to gain complete API-level visibility into your S3 transactions.
4. Deploy GuardDuty with explicit S3 protection. It is important to note that S3 protection is a separate toggle within GuardDuty and is not enabled by default in all configuration types. Simply deploying base GuardDuty is insufficient for S3 protection.
Integrate your ticketing system with Security Hub and the CIS AWS Foundations Benchmark to track your findings with your ticketing system (Jira, ServiceNow, Linear, etc.) A compliance violation that has no owner %u2013 it is a vulnerability that will remain unaddressed.
Implement least-privilege IAM policies on every service role. For example, remove all wildcard s3:* permissions, and only use specific actions which correspond to a specific bucket ARN. Run the IAM Access Analyzer each month to identify drift before the attackers do.
Ensure that you scan all of your code repositories for hardcoded secrets. Use TruffleHog or GitGuardian as your pre-commit hooks. If you have GitHub Advanced Security enabled it will automatically provide ongoing protection against hardcoded secrets in your CI/CD process.
If you have exposed credentials, you must immediately rotate them. Simply deactivating the credentials is not enough.
Run a quarterly automated scan for misconfigurations. Prowler, ScoutSuite and AWS Config Conformance Packs provide continuous evaluation of your S3 posture and will alert you to any misconfiguration in relation to your defined security baseline. Monitoring your S3 status through the tools listed above is the last layer of defense for any misconfigured S3 bucket to avoid a data breach.
Lessons Learned
1. Default settings can be dangerous. AWS's choice to set the default setting for new buckets to private is an improvement over previous years when new buckets had default settings that were public and led to breaches. However, some legacy buckets are still using default settings that can cause a potential breach. You cannot assume buckets are private so ensure you check programmatically and continuously with AWS Config or Prowler.
2. Without an alerting system, logging is not useful. NovaPay used CloudTrail and had GuardDuty turned on; however, none of those tools were integrated with a method to trigger an action when there was evidence of an incident. Therefore, logs are worthless unless there are corresponding alert conditions and runbooks tied to those logs. You must create EventBridge rules and integrate them with PagerDuty or another alerting system so that if there is a finding, it is investigated.
3. The distance of damage from a single attack is greater than you anticipate. The misconfigured bucket was the entry point. The second incident was the use of hard-coded credentials stored in the bucket data. The over-privileged IAM role was the third instance that caused extensive additional damage to the environment. Cloud environments are complex systems where services affect one another and a compromise in one service can lead to compromises in multiple other services. You need to document the distance for which damage could occur before an attacker does.
4. This security breach indicates both a technical issue and also a failure in the process of securing the system. When there are extra steps involved in securing something compared to not securing something, developers who are given a deadline will tend to take those shortcuts when developing code for their application because time is of the essence. By automating the Block Public Access feature at the account-level, and enforcing it through Service Control Policies (SCPs) in an AWS Organization will create a situation that makes it very unlikely that developers will accidentally expose a bucket.
Conclusion
NovaPay's breach was not the result of a nation-state attack executed using advanced methods; rather, it was the result of multiple instances of exploiting Cloud misconfiguration risks.
The attacker leveraged widely available, free tools to perform a "Google" search for an accidentally left completely open bucket and downloaded 340 GB (340 GB!) of customer data from that bucket without the victim being aware the data had been taken. The attacker used that customer data to find credentials to access NovaPay's environment, escalate privileges and ultimately monetize their illicit access - and the entire attack was completed in just 72 hours.
This incident exemplifies Cloud misconfiguration risk in every sense: those types of errors can create insurmountable risk to their owners and are incredibly easy to exploit. An attacker has no barriers in order to perpetrate their abuse, but the impact an attacker has on their target can have devastating regulatory penalties, customer notifications, reputational damage, and expedited Incident Response. All of these are the direct result of one single developer clicking the wrong option within the AWS console.












.png)


.png)



.png)