AWS S3 Bucket Policy Added to Share with External Account
Detects when an Amazon S3 bucket policy is modified to share access with an external AWS account. This rule analyzes PutBucketPolicy events and compares the S3 bucket’s account ID to any account IDs referenced in the policy’s Effect=Allow statements. If the policy includes principals from accounts other than the bucket owner’s, the rule triggers an alert. This behavior may indicate an adversary backdooring a bucket for data exfiltration or cross-account persistence. For example, an attacker who compromises credentials could attach a policy allowing access from an external AWS account they control, enabling continued access even after credentials are rotated. Note: This rule will not alert if the account ID is part of the bucket’s name or appears in the resource ARN. Such cases are common in standardized naming conventions (e.g., “mybucket-123456789012”). To ensure full coverage, use complementary rules to monitor for suspicious PutBucketPolicy API requests targeting buckets with account IDs embedded in their names or resources.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2024/04/17"
3integration = ["aws"]
4maturity = "production"
5updated_date = "2025/10/30"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects when an Amazon S3 bucket policy is modified to share access with an external AWS account. This rule analyzes
11PutBucketPolicy events and compares the S3 bucket’s account ID to any account IDs referenced in the policy’s
12Effect=Allow statements. If the policy includes principals from accounts other than the bucket owner’s, the rule
13triggers an alert. This behavior may indicate an adversary backdooring a bucket for data exfiltration or cross-account
14persistence. For example, an attacker who compromises credentials could attach a policy allowing access from an external
15AWS account they control, enabling continued access even after credentials are rotated. Note: This rule will not alert
16if the account ID is part of the bucket’s name or appears in the resource ARN. Such cases are common in standardized
17naming conventions (e.g., “mybucket-123456789012”). To ensure full coverage, use complementary rules to monitor for
18suspicious PutBucketPolicy API requests targeting buckets with account IDs embedded in their names or resources.
19"""
20event_category_override = "event.type"
21false_positives = [
22 """
23 Legitimate changes to share an S3 bucket with an external account may be identified as false positives.
24 """,
25]
26index = ["filebeat-*", "logs-aws.cloudtrail-*"]
27language = "eql"
28license = "Elastic License v2"
29name = "AWS S3 Bucket Policy Added to Share with External Account"
30note = """## Triage and analysis
31
32> **Disclaimer**:
33> 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.
34
35### Investigating AWS S3 Bucket Policy Added to Share with External Account
36
37This rule detects when an S3 bucket policy is modified using the `PutBucketPolicy` API call to include an external AWS account ID.
38It compares the bucket’s `recipient_account_id` to any account IDs included in the policy’s `Effect=Allow` statement, triggering
39an alert if the two do not match.
40
41Adversaries may exploit this to backdoor a bucket and exfiltrate sensitive data by granting permissions to another AWS account
42they control, enabling ongoing access to the bucket’s contents even if IAM credentials are rotated or revoked.
43
44This detection specifically focuses on policy-based sharing and does not alert when:
45- The account ID appears within the bucket or object name being shared.
46- The account owner explicitly matches the policy’s condition keys on something other than an ARN or account id (i.e. IP address).
47
48To fully monitor for suspicious sharing behavior, use this rule in combination with detections for:
49- Unusual PutBucketPolicy requests
50- Cross-account object access (e.g., `GetObject`, `PutObject`)
51- Changes to bucket ACLs or access points
52
53#### Possible investigation steps
54
55- **Identify the Actor and Context**
56 - Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id` to identify who made the change.
57 - Determine if the identity typically manages S3 bucket policies.
58 - Examine `aws.cloudtrail.resources.arn` to determine which bucket is being shared.
59
60- **Analyze the Policy Change**
61 - Review `aws.cloudtrail.request_parameters` to extract the policy JSON and identify the external AWS account ID(s) referenced.
62 - Check for `Effect=Allow` statements granting broad permissions such as `"Action": "s3:*"` or `"Resource": "*"`.
63 - Verify if the added principals correspond to known partners or external vendors.
64 - If AWS account ID(s) were only part of `Effect=Deny` statements, then this rule can be closed as a false positive.
65
66- **Review Context and Source**
67 - Check `source.ip`, `source.geo`, and `user_agent.original` for anomalies — such as new IP ranges, access from unfamiliar geographies, or use of programmatic clients (`boto3`, `aws-cli`).
68
69- **Correlate with Related Activity**
70 - Search CloudTrail for subsequent activity by the external AWS account ID(s):
71 - `GetObject`, `ListBucket`, or `PutObject` events that indicate data access or exfiltration.
72 - Look for additional configuration changes by the same actor, such as:
73 - `PutBucketAcl`, `PutBucketVersioning`, or `PutBucketReplication` — often part of a larger bucket compromise chain.
74 - Determine if multiple buckets were modified in quick succession.
75
76- **Validate Intent**
77 - Review internal change requests or documentation to confirm whether this external sharing was approved.
78 - If no approval exists, escalate immediately for potential compromise.
79
80### False positive analysis
81
82- **Authorized Cross-Account Access**
83 - Some organizations legitimately share S3 buckets across accounts within a trusted AWS Organization or partner accounts.
84 - Validate whether the external account ID belongs to a known entity or service provider and is documented in your allowlist.
85- **Automation or Deployment Pipelines**
86 - Continuous integration/deployment pipelines may temporarily attach cross-account policies for replication or staging.
87 - Verify the `user_agent.original` or role name — automation often includes identifiable strings.
88- **Naming and Rule Logic Limitations**
89 - This rule excludes detections where the account ID appears in the bucket resource ARN (e.g., `mybucket-123456789012`).
90 - Such patterns are common in automated provisioning. For those scenarios, rely on complementary rules that directly monitor `PutBucketPolicy` events against those buckets.
91
92### Response and remediation
93
94- **Immediate Review and Containment**
95 - If unauthorized sharing is confirmed, use the AWS CLI or Console to delete or revert the modified policy (`aws s3api delete-bucket-policy` or restore from version control).
96 - Remove external principals and reapply the correct bucket policy.
97 - Rotate access keys for the actor involved, especially if API access came from unexpected locations or tools.
98
99- **Investigation and Scoping**
100 - Identify whether data was accessed by the external account via `GetObject` or `ListBucket` operations.
101 - Search CloudTrail logs for other buckets modified by the same actor or IP within the same timeframe.
102 - Use AWS Config to review version history of affected bucket policies and detect similar cross-account permissions.
103
104- **Recovery and Hardening**
105 - Restrict `s3:PutBucketPolicy` to a limited set of administrative roles using least privilege.
106 - Enable AWS Config rule `s3-bucket-policy-grantee-check` to monitor for unauthorized policy additions.
107 - Use AWS GuardDuty or Security Hub findings to correlate policy changes with data exfiltration or credential compromise events.
108 - Apply service control policies (SCPs) to block cross-account sharing unless explicitly approved.
109
110### Additional information
111 - **[AWS IR Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/blob/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks/)**
112 - **[AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework/tree/a8c7b313636b406a375952ac00b2d68e89a991f2/docs)**
113 - **Security Best Practices:** [AWS Knowledge Center – Security Best Practices](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/).
114"""
115references = [
116 "https://stratus-red-team.cloud/attack-techniques/AWS/aws.exfiltration.s3-backdoor-bucket-policy/",
117 "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html",
118]
119risk_score = 47
120rule_id = "e8c9ff14-fd1e-11ee-a0df-f661ea17fbce"
121severity = "medium"
122tags = [
123 "Domain: Cloud",
124 "Data Source: AWS",
125 "Data Source: Amazon Web Services",
126 "Data Source: AWS S3",
127 "Use Case: Threat Detection",
128 "Tactic: Exfiltration",
129 "Tactic: Collection",
130 "Resources: Investigation Guide",
131]
132timestamp_override = "event.ingested"
133type = "eql"
134
135query = '''
136info where event.dataset == "aws.cloudtrail"
137 and event.provider == "s3.amazonaws.com"
138 and event.action == "PutBucketPolicy"
139 and stringContains(aws.cloudtrail.request_parameters, "Effect=Allow")
140 and (
141 stringContains(aws.cloudtrail.request_parameters, "AWS=") or
142 stringContains(aws.cloudtrail.request_parameters, "aws:PrincipalAccount=") or
143 stringContains(aws.cloudtrail.request_parameters, "aws:SourceAccount=")
144 )
145and not stringContains(aws.cloudtrail.request_parameters, "arn:aws:cloudfront::")
146and not stringContains(aws.cloudtrail.request_parameters, "arn:aws:iam::cloudfront:user")
147and not stringContains(aws.cloudtrail.request_parameters, aws.cloudtrail.recipient_account_id)
148'''
149
150
151[[rule.threat]]
152framework = "MITRE ATT&CK"
153[[rule.threat.technique]]
154id = "T1537"
155name = "Transfer Data to Cloud Account"
156reference = "https://attack.mitre.org/techniques/T1537/"
157
158
159[rule.threat.tactic]
160id = "TA0010"
161name = "Exfiltration"
162reference = "https://attack.mitre.org/tactics/TA0010/"
163[[rule.threat]]
164framework = "MITRE ATT&CK"
165[[rule.threat.technique]]
166id = "T1530"
167name = "Data from Cloud Storage"
168reference = "https://attack.mitre.org/techniques/T1530/"
169
170
171[rule.threat.tactic]
172id = "TA0009"
173name = "Collection"
174reference = "https://attack.mitre.org/tactics/TA0009/"
175
176[rule.investigation_fields]
177field_names = [
178 "@timestamp",
179 "user.name",
180 "user_agent.original",
181 "source.ip",
182 "aws.cloudtrail.user_identity.arn",
183 "aws.cloudtrail.user_identity.type",
184 "aws.cloudtrail.user_identity.access_key_id",
185 "aws.cloudtrail.resources.arn",
186 "aws.cloudtrail.resources.type",
187 "event.action",
188 "event.outcome",
189 "cloud.account.id",
190 "cloud.region",
191 "aws.cloudtrail.request_parameters",
192 "aws.cloudtrail.response_elements",
193]
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 Policy Added to Share with External Account
This rule detects when an S3 bucket policy is modified using the PutBucketPolicy API call to include an external AWS account ID.
It compares the bucket’s recipient_account_id to any account IDs included in the policy’s Effect=Allow statement, triggering
an alert if the two do not match.
Adversaries may exploit this to backdoor a bucket and exfiltrate sensitive data by granting permissions to another AWS account they control, enabling ongoing access to the bucket’s contents even if IAM credentials are rotated or revoked.
This detection specifically focuses on policy-based sharing and does not alert when:
- The account ID appears within the bucket or object name being shared.
- The account owner explicitly matches the policy’s condition keys on something other than an ARN or account id (i.e. IP address).
To fully monitor for suspicious sharing behavior, use this rule in combination with detections for:
- Unusual PutBucketPolicy requests
- Cross-account object access (e.g.,
GetObject,PutObject) - Changes to bucket ACLs or access points
Possible investigation steps
-
Identify the Actor and Context
- Review
aws.cloudtrail.user_identity.arnandaws.cloudtrail.user_identity.access_key_idto identify who made the change. - Determine if the identity typically manages S3 bucket policies.
- Examine
aws.cloudtrail.resources.arnto determine which bucket is being shared.
- Review
-
Analyze the Policy Change
- Review
aws.cloudtrail.request_parametersto extract the policy JSON and identify the external AWS account ID(s) referenced. - Check for
Effect=Allowstatements granting broad permissions such as"Action": "s3:*"or"Resource": "*". - Verify if the added principals correspond to known partners or external vendors.
- If AWS account ID(s) were only part of
Effect=Denystatements, then this rule can be closed as a false positive.
- Review
-
Review Context and Source
- Check
source.ip,source.geo, anduser_agent.originalfor anomalies — such as new IP ranges, access from unfamiliar geographies, or use of programmatic clients (boto3,aws-cli).
- Check
-
Correlate with Related Activity
- Search CloudTrail for subsequent activity by the external AWS account ID(s):
GetObject,ListBucket, orPutObjectevents that indicate data access or exfiltration.
- Look for additional configuration changes by the same actor, such as:
PutBucketAcl,PutBucketVersioning, orPutBucketReplication— often part of a larger bucket compromise chain.
- Determine if multiple buckets were modified in quick succession.
- Search CloudTrail for subsequent activity by the external AWS account ID(s):
-
Validate Intent
- Review internal change requests or documentation to confirm whether this external sharing was approved.
- If no approval exists, escalate immediately for potential compromise.
False positive analysis
- Authorized Cross-Account Access
- Some organizations legitimately share S3 buckets across accounts within a trusted AWS Organization or partner accounts.
- Validate whether the external account ID belongs to a known entity or service provider and is documented in your allowlist.
- Automation or Deployment Pipelines
- Continuous integration/deployment pipelines may temporarily attach cross-account policies for replication or staging.
- Verify the
user_agent.originalor role name — automation often includes identifiable strings.
- Naming and Rule Logic Limitations
- This rule excludes detections where the account ID appears in the bucket resource ARN (e.g.,
mybucket-123456789012). - Such patterns are common in automated provisioning. For those scenarios, rely on complementary rules that directly monitor
PutBucketPolicyevents against those buckets.
- This rule excludes detections where the account ID appears in the bucket resource ARN (e.g.,
Response and remediation
-
Immediate Review and Containment
- If unauthorized sharing is confirmed, use the AWS CLI or Console to delete or revert the modified policy (
aws s3api delete-bucket-policyor restore from version control). - Remove external principals and reapply the correct bucket policy.
- Rotate access keys for the actor involved, especially if API access came from unexpected locations or tools.
- If unauthorized sharing is confirmed, use the AWS CLI or Console to delete or revert the modified policy (
-
Investigation and Scoping
- Identify whether data was accessed by the external account via
GetObjectorListBucketoperations. - Search CloudTrail logs for other buckets modified by the same actor or IP within the same timeframe.
- Use AWS Config to review version history of affected bucket policies and detect similar cross-account permissions.
- Identify whether data was accessed by the external account via
-
Recovery and Hardening
- Restrict
s3:PutBucketPolicyto a limited set of administrative roles using least privilege. - Enable AWS Config rule
s3-bucket-policy-grantee-checkto monitor for unauthorized policy additions. - Use AWS GuardDuty or Security Hub findings to correlate policy changes with data exfiltration or credential compromise events.
- Apply service control policies (SCPs) to block cross-account sharing unless explicitly approved.
- Restrict
Additional information
- AWS IR Playbooks
- AWS Customer Playbook Framework
- Security Best Practices: AWS Knowledge Center – Security Best Practices.
References
Related rules
- AWS S3 Bucket Policy Added to Allow Public Access
- AWS SNS Rare Protocol Subscription by User
- AWS S3 Bucket Replicated to Another Account
- AWS S3 Bucket Enumeration or Brute Force
- Potential AWS S3 Bucket Ransomware Note Uploaded