AWS S3 Bucket ACL Modified to Allow Public Access by New Identity
Detects a principal modifying an S3 bucket ACL to grant public read or write access that has not been observed doing so within the history window, using canned ACLs such as public-read or public-read-write. ACL-based public access is a distinct API path (PutBucketAcl) that can bypass some Block Public Access controls. Monitoring for new identities performing this change helps surface freshly compromised credentials being used to stage data for exfiltration or inadvertently expose sensitive content.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/07/27"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2026/07/27"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects a principal modifying an S3 bucket ACL to grant public read or write access that has not
11been observed doing so within the history window, using canned ACLs such as public-read or
12public-read-write. ACL-based public access is a distinct API path (PutBucketAcl) that can bypass
13some Block Public Access controls. Monitoring for new identities performing this change helps surface
14freshly compromised credentials being used to stage data for exfiltration or inadvertently expose sensitive
15content.
16"""
17false_positives = [
18 """
19 Static website hosting configurations may intentionally use a public-read ACL on S3 buckets
20 that serve web content. Validate that the target bucket is a known public-facing asset and that
21 the change was authorized. Consider adding exclusions for specific bucket names used for static
22 hosting.
23 """,
24]
25from = "now-6m"
26index = ["logs-aws.cloudtrail-*"]
27interval = "5m"
28language = "kuery"
29license = "Elastic License v2"
30name = "AWS S3 Bucket ACL Modified to Allow Public Access by New Identity"
31note = """## Triage and analysis
32
33### Investigating AWS S3 Bucket ACL Modified to Allow Public Access by New Identity
34
35This rule fires when a `PutBucketAcl` call sets a canned ACL that grants public or broad access. Unlike bucket policies, bucket ACLs are a legacy mechanism that bypasses some newer Block Public Access controls and can inadvertently or deliberately expose bucket contents to unauthenticated internet users.
36
37### Possible investigation steps
38
39- Identify the modifying principal (`aws.cloudtrail.user_identity.arn`) and determine whether they are authorized to modify S3 bucket ACLs.
40- Review `aws.cloudtrail.request_parameters` to confirm the specific canned ACL applied (`public-read`, `public-read-write`).
41- Check whether AWS S3 Block Public Access is enabled at the account or bucket level — if so, it may still be preventing effective public exposure even though this ACL change succeeded.
42- Enumerate the bucket contents to assess the sensitivity of any exposed data.
43- Check for recent `GetObject` or `ListObjects` calls from unauthenticated sources against the same bucket.
44
45### False positive analysis
46
47- Static website hosting buckets are commonly configured with `public-read` ACLs.
48
49### Response and remediation
50
51- If unauthorized, immediately reset the bucket ACL to `private` using `PutBucketAcl`.
52- Enable S3 Block Public Access at the account level to prevent future ACL-based public exposure across all buckets.
53- Review the bucket's object-level access log for any unauthorized reads that occurred after the ACL change.
54"""
55references = [
56 "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html",
57 "https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-overview.html",
58]
59risk_score = 47
60rule_id = "3e7c1b84-9f52-4d63-8a17-6b0e4c2f9d31"
61setup = "The AWS CloudTrail integration must be enabled and configured to collect S3 management events (`s3.amazonaws.com`)."
62severity = "medium"
63tags = [
64 "Domain: Cloud",
65 "Data Source: AWS",
66 "Data Source: Amazon Web Services",
67 "Data Source: Amazon S3",
68 "Use Case: Threat Detection",
69 "Tactic: Collection",
70 "Resources: Investigation Guide",
71]
72timestamp_override = "event.ingested"
73type = "new_terms"
74
75query = '''
76data_stream.dataset: "aws.cloudtrail"
77 and event.provider: "s3.amazonaws.com"
78 and event.action: "PutBucketAcl"
79 and event.outcome: "success"
80 and not aws.cloudtrail.user_identity.type: "AWSService"
81 and aws.cloudtrail.flattened.request_parameters.x-amz-acl: ("public-read" or "public-read-write")
82 and not user_agent.original: (*Terraform* or *terraform* or "cloudformation.amazonaws.com" or *pulumi* or *Pulumi*)
83'''
84
85[[rule.threat]]
86framework = "MITRE ATT&CK"
87
88[[rule.threat.technique]]
89id = "T1530"
90name = "Data from Cloud Storage"
91reference = "https://attack.mitre.org/techniques/T1530/"
92
93[rule.threat.tactic]
94id = "TA0009"
95name = "Collection"
96reference = "https://attack.mitre.org/tactics/TA0009/"
97
98[rule.new_terms]
99field = "new_terms_fields"
100value = ["aws.cloudtrail.user_identity.arn"]
101[[rule.new_terms.history_window_start]]
102field = "history_window_start"
103value = "now-7d"
104
105[rule.investigation_fields]
106field_names = [
107 "@timestamp",
108 "aws.cloudtrail.user_identity.arn",
109 "aws.cloudtrail.user_identity.type",
110 "event.action",
111 "event.outcome",
112 "aws.cloudtrail.request_parameters",
113 "source.ip",
114 "cloud.region",
115 "cloud.account.id",
116]
Triage and analysis
Investigating AWS S3 Bucket ACL Modified to Allow Public Access by New Identity
This rule fires when a PutBucketAcl call sets a canned ACL that grants public or broad access. Unlike bucket policies, bucket ACLs are a legacy mechanism that bypasses some newer Block Public Access controls and can inadvertently or deliberately expose bucket contents to unauthenticated internet users.
Possible investigation steps
- Identify the modifying principal (
aws.cloudtrail.user_identity.arn) and determine whether they are authorized to modify S3 bucket ACLs. - Review
aws.cloudtrail.request_parametersto confirm the specific canned ACL applied (public-read,public-read-write). - Check whether AWS S3 Block Public Access is enabled at the account or bucket level — if so, it may still be preventing effective public exposure even though this ACL change succeeded.
- Enumerate the bucket contents to assess the sensitivity of any exposed data.
- Check for recent
GetObjectorListObjectscalls from unauthenticated sources against the same bucket.
False positive analysis
- Static website hosting buckets are commonly configured with
public-readACLs.
Response and remediation
- If unauthorized, immediately reset the bucket ACL to
privateusingPutBucketAcl. - Enable S3 Block Public Access at the account level to prevent future ACL-based public exposure across all buckets.
- Review the bucket's object-level access log for any unauthorized reads that occurred after the ACL change.
References
Related rules
- AWS S3 Rapid Bucket Posture API Calls from a Single Principal
- AWS S3 Bucket Policy Added to Allow Public Access
- AWS S3 Bucket Policy Added to Share with External Account
- AWS S3 Unauthenticated Bucket Access by Rare Source
- AWS SNS Rare Protocol Subscription by User