LoFP LoFP / 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.

Techniques

Sample rules

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.

Detection logic

`cloudtrail`
eventSource="s3.amazonaws.com"
eventName="PutBucketAcl"
errorCode=success
userAgent IN ("[aws-cli*", "aws-cli*")


| rename requestParameters.bucketName AS bucketName
         requestParameters.accessControlList.x-amz-grant-read AS grantRead
         requestParameters.accessControlList.x-amz-grant-read-acp AS grantReadAcp
         requestParameters.accessControlList.x-amz-grant-write AS grantWrite
         requestParameters.accessControlList.x-amz-grant-write-acp AS grantWriteAcp
         requestParameters.accessControlList.x-amz-grant-full-control AS grantFullControl
         requestParameters.x-amz-acl AS cannedAcl,
         userIdentity.principalId AS principalId
         userIdentity.userName AS userName
         userIdentity.arn AS userArn


| eval grantRead=coalesce(grantRead,"-"),
       grantReadAcp=coalesce(grantReadAcp,"-"),
       grantWrite=coalesce(grantWrite,"-"),
       grantWriteAcp=coalesce(grantWriteAcp,"-"),
       grantFullControl=coalesce(grantFullControl,"-"),
       cannedAcl=coalesce(cannedAcl,"-"),
       user=coalesce(userName,userArn)


| eval publicGrant = if(
                        match(grantRead, "(?i)AllUsers
|AuthenticatedUsers")
                        OR
                        match(grantReadAcp, "(?i)AllUsers
|AuthenticatedUsers")
                        OR
                        match(grantWrite, "(?i)AllUsers
|AuthenticatedUsers")
                        OR
                        match(grantWriteAcp, "(?i)AllUsers
|AuthenticatedUsers")
                        OR
                        match(grantFullControl, "(?i)AllUsers
|AuthenticatedUsers"),
                        1,
                        0
                    )


| eval publicCanned = if(cannedAcl IN ("public-read", "public-read-write", "authenticated-read"), 1, 0)


| where publicGrant=1 OR publicCanned=1


| 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")


| stats count
        min(_time) AS firstTime
        max(_time) AS lastTime
        values(cannedAcl) AS cannedAcl
        values(grantRead) AS grantRead
        values(grantReadAcp) AS grantReadAcp
        values(grantWrite) AS grantWrite
        values(grantWriteAcp) AS grantWriteAcp
        values(grantFullControl) AS grantFullControl
        values(eventName) AS eventName

  BY user principalId userAgent bucketName exposure


| `security_content_ctime(firstTime)`

| `security_content_ctime(lastTime)`

| `detect_new_open_s3_buckets_over_aws_cli_filter`