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.arn and aws.cloudtrail.user_identity.access_key_id to identify who made the change.
    • Determine if the identity typically manages S3 bucket policies.
    • Examine aws.cloudtrail.resources.arn to determine which bucket is being shared.
  • Analyze the Policy Change

    • Review aws.cloudtrail.request_parameters to extract the policy JSON and identify the external AWS account ID(s) referenced.
    • Check for Effect=Allow statements 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=Deny statements, then this rule can be closed as a false positive.
  • Review Context and Source

    • 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).
  • Correlate with Related Activity

    • Search CloudTrail for subsequent activity by the external AWS account ID(s):
      • GetObject, ListBucket, or PutObject events that indicate data access or exfiltration.
    • Look for additional configuration changes by the same actor, such as:
      • PutBucketAcl, PutBucketVersioning, or PutBucketReplication — often part of a larger bucket compromise chain.
    • Determine if multiple buckets were modified in quick succession.
  • 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.original or 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 PutBucketPolicy events against those buckets.

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-policy or 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.
  • Investigation and Scoping

    • Identify whether data was accessed by the external account via GetObject or ListBucket operations.
    • 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.
  • Recovery and Hardening

    • Restrict s3:PutBucketPolicy to a limited set of administrative roles using least privilege.
    • Enable AWS Config rule s3-bucket-policy-grantee-check to 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.

Additional information

References

Related rules

to-top