| ID | Technique | Tactic |
|---|---|---|
| T1530 | Data from Cloud Storage | Collection |
Detection: Detect New Open S3 Buckets over AWS CLI
Description
The following analytic detects the creation of open/public S3 buckets via the AWS CLI. It leverages AWS CloudTrail logs to identify events where a user has set bucket permissions to allow access to "AuthenticatedUsers" or "AllUsers." This activity is significant because open S3 buckets can expose sensitive data to unauthorized users, leading to data breaches. If confirmed malicious, an attacker could gain unauthorized access to potentially sensitive information stored in the S3 bucket, posing a significant security risk.
Search
1`cloudtrail`
2eventSource="s3.amazonaws.com"
3eventName="PutBucketAcl"
4errorCode=success
5userAgent IN ("[aws-cli*", "aws-cli*")
6
7
8| rename requestParameters.bucketName AS bucketName
9 requestParameters.accessControlList.x-amz-grant-read AS grantRead
10 requestParameters.accessControlList.x-amz-grant-read-acp AS grantReadAcp
11 requestParameters.accessControlList.x-amz-grant-write AS grantWrite
12 requestParameters.accessControlList.x-amz-grant-write-acp AS grantWriteAcp
13 requestParameters.accessControlList.x-amz-grant-full-control AS grantFullControl
14 requestParameters.x-amz-acl AS cannedAcl,
15 userIdentity.principalId AS principalId
16 userIdentity.userName AS userName
17 userIdentity.arn AS userArn
18
19
20| eval grantRead=coalesce(grantRead,"-"),
21 grantReadAcp=coalesce(grantReadAcp,"-"),
22 grantWrite=coalesce(grantWrite,"-"),
23 grantWriteAcp=coalesce(grantWriteAcp,"-"),
24 grantFullControl=coalesce(grantFullControl,"-"),
25 cannedAcl=coalesce(cannedAcl,"-"),
26 user=coalesce(userName,userArn)
27
28
29| eval publicGrant = if(
30 match(grantRead, "(?i)AllUsers
31|AuthenticatedUsers")
32 OR
33 match(grantReadAcp, "(?i)AllUsers
34|AuthenticatedUsers")
35 OR
36 match(grantWrite, "(?i)AllUsers
37|AuthenticatedUsers")
38 OR
39 match(grantWriteAcp, "(?i)AllUsers
40|AuthenticatedUsers")
41 OR
42 match(grantFullControl, "(?i)AllUsers
43|AuthenticatedUsers"),
44 1,
45 0
46 )
47
48
49| eval publicCanned = if(cannedAcl IN ("public-read", "public-read-write", "authenticated-read"), 1, 0)
50
51
52| where publicGrant=1 OR publicCanned=1
53
54
55| eval exposure=case(cannedAcl=="public-read-write","public-write", match(grantWrite."".grantWriteAcp."".grantFullControl,"(?i)AllUsers"),"public-write", cannedAcl=="public-read" OR match(grantRead,"(?i)AllUsers"),"public-read", cannedAcl=="authenticated-read" OR match(grantRead,"(?i)AuthenticatedUsers"),"authenticated-read", true(),"custom-grant")
56
57
58| stats count
59 min(_time) AS firstTime
60 max(_time) AS lastTime
61 values(cannedAcl) AS cannedAcl
62 values(grantRead) AS grantRead
63 values(grantReadAcp) AS grantReadAcp
64 values(grantWrite) AS grantWrite
65 values(grantWriteAcp) AS grantWriteAcp
66 values(grantFullControl) AS grantFullControl
67 values(eventName) AS eventName
68
69 BY user principalId userAgent bucketName exposure
70
71
72| `security_content_ctime(firstTime)`
73
74| `security_content_ctime(lastTime)`
75
76| `detect_new_open_s3_buckets_over_aws_cli_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| AWS CloudTrail | 'aws:cloudtrail' |
'aws_cloudtrail' |
Macros Used
| Name | Value |
|---|---|
| security_content_ctime | convert timeformat="%Y-%m-%dT%H:%M:%S" ctime($field$) |
| detect_new_open_s3_buckets_over_aws_cli_filter | search * |
detect_new_open_s3_buckets_over_aws_cli_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.
Annotations
Default Configuration
This detection is configured by default in Splunk Enterprise Security to run with the following settings:
| Setting | Value |
|---|---|
| Disabled | true |
| Cron Schedule | 0 * * * * |
| Earliest Time | -70m@m |
| Latest Time | -10m@m |
| Schedule Window | auto |
| Creates Finding (Notable) | Yes |
| Rule Title | %name% |
| Rule Description | %description% |
| Notable Event Fields | user, dest |
| Creates Intermediate Finding (Risk Event) | No |
Implementation
The Splunk AWS Add-on and Splunk App for AWS is required to utilize this data. The search requires AWS Cloudtrail logs.
Known False Positives
It is possible that an AWS admin has legitimately created a public bucket for a specific purpose. AWS strongly advises against granting full control to the "All Users" group. Investigate and apply the necessary filters as needed.
Associated Analytic Story
Finding
| Title | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| User [$user$] has created an open/public S3 Bucket [$bucketName$] using AWS CLI with the following permissions - [$grantRead$] [$grantReadAcp$] [$grantWrite$] [$grantWriteAcp$] [$grantFullControl$] [$cannedAcl$] | user | user | 50 |
Threat Objects
| Field | Type |
|---|---|
| bucketName | bucket_name |
References
Detection Testing
| Test Type | Status | Dataset | Source | Sourcetype |
|---|---|---|---|---|
| Validation | ✅ Passing | N/A | N/A | N/A |
| Unit | ✅ Passing | Dataset | aws_cloudtrail |
aws:cloudtrail |
| Integration | ✅ Passing | Dataset | aws_cloudtrail |
aws:cloudtrail |
Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI.
Alternatively you can replay a dataset into a Splunk Attack Range
Source: GitHub |
Version: 11