AWS S3 Bucket Enumeration or Brute Force

Identifies a high number of failed S3 operations against a single bucket from a single source address within a short timeframe. This activity can indicate attempts to collect bucket objects or cause an increase in billing to an account via internal "AccessDenied" errors.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2024/05/01"
  3integration = ["aws"]
  4maturity = "production"
  5updated_date = "2025/10/01"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies a high number of failed S3 operations against a single bucket from a single source address within a short timeframe. 
 11This activity can indicate attempts to collect bucket objects or cause an increase in billing to an account via internal "AccessDenied" errors.
 12"""
 13false_positives = [
 14  """
 15  External account IDs or broken automation may trigger this rule. For AccessDenied (HTTP 403 Forbidden), S3 doesn't charge the bucket owner when the request is initiated outside of the bucket owner's individual AWS account or the bucket owner's AWS organization.
 16  """]
 17from = "now-6m"
 18index = ["logs-aws.cloudtrail-*"]
 19language = "kuery"
 20license = "Elastic License v2"
 21name = "AWS S3 Bucket Enumeration or Brute Force"
 22note = """
 23## Triage and analysis
 24
 25> **Disclaimer**:
 26> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
 27
 28### Investigating AWS S3 Bucket Enumeration or Brute Force
 29
 30This rule detects when many failed S3 operations (HTTP 403 AccessDenied) hit a single bucket from a single source address in a short window. This can indicate bucket name enumeration, object/key guessing, or brute-force style traffic intended to drive cost or probe for misconfigurations. 403 requests from outside the bucket owner’s account/organization are not billed, but 4XX from inside the owner’s account/org can still incur charges. Prioritize confirming who is making the calls and where they originate.
 31
 32#### Possible investigation steps
 33
 34- **Investigate in Timeline.** Investigate the alert in timeline (Take action -> Investigate in timeline) to retrieve and review all of the raw CloudTrail events that contributed to the threshold alert. Threshold alerts only display the grouped fields; Timeline provides a way to see individual event details such as request parameters, full error messages, and additional user context.  
 35- **Confirm entity & target.** Note the rule’s threshold and window. Identify the target bucket (`tls.client.server_name`) and the source (`source.address`). Verify the caller identity details via any available `aws.cloudtrail.user_identity` fields.  
 36- **Actor & session context.** In CloudTrail events, pivot 15–30 minutes around the spike for the same `source.address` or principal. Determine if the source is:
 37  - **External** to your account/organization (recon/cost DDoS risk is lower for you due to 2024 billing change).  
 38  - **Internal** (same account/org)—higher cost risk and possible misuse of internal automation.  
 39- **Bucket posture snapshot.** Record S3 Block Public Access, Bucket Policy, ACLs, and whether Versioning/Object Lock are enabled. Capture any recent `PutBucketPolicy`, `PutPublicAccessBlock`, `PutBucketVersioning`, or lifecycle changes.  
 40- **Blast radius.** Check for similar spikes to other buckets/regions, or parallel spikes from the same source. Review any GuardDuty S3 findings and AWS Config drift related to the bucket or principal.  
 41- **Business context.** Contact the bucket/app owner. Validate whether a migration, scanner, or broken job could legitimately cause bursts.  
 42
 43### False positive analysis
 44
 45- **Expected jobs / broken automation.** Data movers, posture scanners, or failed credentials can generate 403 storms. Validate with `userAgent`, ARNs, change windows, and environment (dev/stage vs prod).  
 46- **External probing.** Internet-origin enumeration often looks like uniform 403s from transient or cloud-provider IPs and typically has no business impact and no billing if outside your account/org. Tune thresholds or allowlist known scanners if appropriate.  
 47
 48### Response and remediation
 49
 50**1. Immediate, low-risk actions**
 51- **Preserve evidence.** Export CloudTrail records (±30 minutes) for the bucket and source address into an evidence bucket with restricted access.  
 52- **Notify owners.** Inform the bucket/application owner and security lead; confirm any maintenance windows.  
 53
 54**2. Containment options**
 55- **External-origin spikes:** Verify Block Public Access is enforced and bucket policies are locked down. Optionally apply a temporary deny-all bucket policy allowing only IR/admin roles while scoping.  
 56- **Internal-origin spikes:** Identify the principal. Rotate access keys for IAM users, or restrict involved roles (temporary deny/SCP, remove risky policies). Pause broken jobs/pipelines until validated.  
 57
 58**3. Scope & hunting**
 59- Review Timeline and CloudTrail for related events: `PutBucketPolicy`, `PutPublicAccessBlock`, `PutBucketVersioning`, lifecycle changes, unusual `PutObject`/`DeleteObject` volumes, or cross-account access.  
 60- Check GuardDuty S3 and Config drift findings for signs of tampering or lateral movement.  
 61
 62**4. Recovery & hardening**
 63- If data impact suspected: with Versioning, restore known-good versions; otherwise, recover from backups/replicas.  
 64- Enable Versioning on critical buckets going forward; evaluate Object Lock legal hold if enabled.  
 65- Ensure Block Public Access, least-privilege IAM policies, CloudTrail data events for S3, and GuardDuty protections are consistently enforced.  
 66
 67### Additional information
 68
 69- [AWS S3 billing for error responses](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ErrorCodeBilling.html): see latest AWS docs on which error codes are billed.  
 70- [AWS announcement (Aug 2024)](https://aws.amazon.com/about-aws/whats-new/2024/05/amazon-s3-no-charge-http-error-codes/): 403s from outside the account/org are not billed.  
 71- [AWS IR Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/): NIST-aligned template for evidence, containment, eradication, recovery, post-incident. 
 72- [AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework/): Practical response steps for account and bucket-level abuse.  
 73"""
 74references = [
 75    "https://medium.com/@maciej.pocwierz/how-an-empty-s3-bucket-can-make-your-aws-bill-explode-934a383cb8b1",
 76    "https://docs.aws.amazon.com/AmazonS3/latest/userguide/ErrorCodeBilling.html",
 77]
 78risk_score = 21
 79rule_id = "5f0234fd-7f21-42af-8391-511d5fd11d5c"
 80severity = "low"
 81tags = [
 82    "Domain: Cloud",
 83    "Data Source: AWS",
 84    "Data Source: Amazon Web Services",
 85    "Data Source: AWS S3",
 86    "Resources: Investigation Guide",
 87    "Use Case: Log Auditing",
 88    "Tactic: Impact",
 89    "Tactic: Discovery",
 90    "Tactic: Collection",
 91]
 92timestamp_override = "event.ingested"
 93type = "threshold"
 94
 95query = '''
 96  event.dataset: "aws.cloudtrail" and 
 97  event.provider : "s3.amazonaws.com" and 
 98  aws.cloudtrail.error_code : "AccessDenied" and 
 99  tls.client.server_name : * 
100'''
101
102[rule.investigation_fields]
103field_names = [
104    "@timestamp",
105    "source.address",
106    "aws.cloudtrail.user_identity.type",
107    "tls.client.server_name"
108]
109
110[[rule.threat]]
111framework = "MITRE ATT&CK"
112[[rule.threat.technique]]
113id = "T1657"
114name = "Financial Theft"
115reference = "https://attack.mitre.org/techniques/T1657/"
116
117
118[rule.threat.tactic]
119id = "TA0040"
120name = "Impact"
121reference = "https://attack.mitre.org/tactics/TA0040/"
122[[rule.threat]]
123framework = "MITRE ATT&CK"
124[[rule.threat.technique]]
125id = "T1619"
126name = "Cloud Storage Object Discovery"
127reference = "https://attack.mitre.org/techniques/T1619/"
128
129[rule.threat.tactic]
130id = "TA0007"
131name = "Discovery"
132reference = "https://attack.mitre.org/tactics/TA0007/"
133[[rule.threat]]
134framework = "MITRE ATT&CK"
135[[rule.threat.technique]]
136id = "T1530"
137name = "Data from Cloud Storage"
138reference = "https://attack.mitre.org/techniques/T1530/"
139
140
141[rule.threat.tactic]
142id = "TA0009"
143name = "Collection"
144reference = "https://attack.mitre.org/tactics/TA0009/"
145
146
147[rule.threshold]
148field = ["tls.client.server_name", "source.address", "aws.cloudtrail.user_identity.type"]
149value = 1
150[[rule.threshold.cardinality]]
151field = "event.id"
152value = 40

Triage and analysis

Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

Investigating AWS S3 Bucket Enumeration or Brute Force

This rule detects when many failed S3 operations (HTTP 403 AccessDenied) hit a single bucket from a single source address in a short window. This can indicate bucket name enumeration, object/key guessing, or brute-force style traffic intended to drive cost or probe for misconfigurations. 403 requests from outside the bucket owner’s account/organization are not billed, but 4XX from inside the owner’s account/org can still incur charges. Prioritize confirming who is making the calls and where they originate.

Possible investigation steps

  • Investigate in Timeline. Investigate the alert in timeline (Take action -> Investigate in timeline) to retrieve and review all of the raw CloudTrail events that contributed to the threshold alert. Threshold alerts only display the grouped fields; Timeline provides a way to see individual event details such as request parameters, full error messages, and additional user context.
  • Confirm entity & target. Note the rule’s threshold and window. Identify the target bucket (tls.client.server_name) and the source (source.address). Verify the caller identity details via any available aws.cloudtrail.user_identity fields.
  • Actor & session context. In CloudTrail events, pivot 15–30 minutes around the spike for the same source.address or principal. Determine if the source is:
    • External to your account/organization (recon/cost DDoS risk is lower for you due to 2024 billing change).
    • Internal (same account/org)—higher cost risk and possible misuse of internal automation.
  • Bucket posture snapshot. Record S3 Block Public Access, Bucket Policy, ACLs, and whether Versioning/Object Lock are enabled. Capture any recent PutBucketPolicy, PutPublicAccessBlock, PutBucketVersioning, or lifecycle changes.
  • Blast radius. Check for similar spikes to other buckets/regions, or parallel spikes from the same source. Review any GuardDuty S3 findings and AWS Config drift related to the bucket or principal.
  • Business context. Contact the bucket/app owner. Validate whether a migration, scanner, or broken job could legitimately cause bursts.

False positive analysis

  • Expected jobs / broken automation. Data movers, posture scanners, or failed credentials can generate 403 storms. Validate with userAgent, ARNs, change windows, and environment (dev/stage vs prod).
  • External probing. Internet-origin enumeration often looks like uniform 403s from transient or cloud-provider IPs and typically has no business impact and no billing if outside your account/org. Tune thresholds or allowlist known scanners if appropriate.

Response and remediation

1. Immediate, low-risk actions

  • Preserve evidence. Export CloudTrail records (±30 minutes) for the bucket and source address into an evidence bucket with restricted access.
  • Notify owners. Inform the bucket/application owner and security lead; confirm any maintenance windows.

2. Containment options

  • External-origin spikes: Verify Block Public Access is enforced and bucket policies are locked down. Optionally apply a temporary deny-all bucket policy allowing only IR/admin roles while scoping.
  • Internal-origin spikes: Identify the principal. Rotate access keys for IAM users, or restrict involved roles (temporary deny/SCP, remove risky policies). Pause broken jobs/pipelines until validated.

3. Scope & hunting

  • Review Timeline and CloudTrail for related events: PutBucketPolicy, PutPublicAccessBlock, PutBucketVersioning, lifecycle changes, unusual PutObject/DeleteObject volumes, or cross-account access.
  • Check GuardDuty S3 and Config drift findings for signs of tampering or lateral movement.

4. Recovery & hardening

  • If data impact suspected: with Versioning, restore known-good versions; otherwise, recover from backups/replicas.
  • Enable Versioning on critical buckets going forward; evaluate Object Lock legal hold if enabled.
  • Ensure Block Public Access, least-privilege IAM policies, CloudTrail data events for S3, and GuardDuty protections are consistently enforced.

Additional information

References

Related rules

to-top