nccgroup / ScoutSuite

Multi-Cloud Security Auditing Tool
GNU General Public License v2.0
6.68k stars 1.06k forks source link

False positive: Bucket Allowing Clear Text (HTTP) Communication (AWS policy key names not case-sensitive) #1525

Open cckev opened 1 year ago

cckev commented 1 year ago

Describe the bug

Using bucket policies, users can deny all S3 actions on a bucket and its contents if the request is not over SSL/TLS (ref: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Boolean). Under certain conditions, ScoutSuite alerts a false positive when AWS users enforce TLS for s3 transport via bucket policy.

The related ScoutSuite finding checks for the condition key name aws:SecureTransport (ref: https://github.com/nccgroup/ScoutSuite/blob/develop/ScoutSuite/providers/aws/facade/s3.py#L270) but does not account for variations of letter cases for the key name.

According to AWS documentation:

Condition key names are not case-sensitive. For example, including the aws:SourceIP condition key is equivalent to testing for AWS:SourceIp.

This means, users can specify the aws:SecureTransport condition key name using any letter casing (ie. aws:securetransport) and still provide a valid bucket policy. The ScoutSuite check likely needs to account for all letter case variations of the key name.

To Reproduce

The following reproduction tests show an s3 bucket policy that uses aws:securetransport for the condition key name and shows that the bucket policy is interpreted differently using all lower casing for aws:securetransport :

Policy 1 (deny http requests)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "BooleanExample",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::test-bucket-for-condition-key-case-sensitivity",
                "arn:aws:s3:::test-bucket-for-condition-key-case-sensitivity/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:securetransport": "false"
                }
            }
        }
    ]
}

Response 1

$ curl -v http://test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com/test.txt
*   Trying 52.216.142.188:80...
* Connected to test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com (52.216.142.188) port 80 (#0)
> GET /test.txt HTTP/1.1
> Host: test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
[snip...]
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>K0JC5NCHW9KCZ7A1</RequestId><HostId>FmpdaEqLHLEa6REt1q0t6vmnEsTYBvOhqZigtFIAYuCbq6VzQc3gK/CsdPuXz3o4WNGkgfemDqg=</HostId></Error>

Policy 2 (allow http requests)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "BooleanExample",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::test-bucket-for-condition-key-case-sensitivity",
                "arn:aws:s3:::test-bucket-for-condition-key-case-sensitivity/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:securetransport": "false"
                }
            }
        }
    ]
}

Response 2

$ curl -v http://test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com/test.txt
*   Trying 52.216.24.4:80...
* Connected to test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com (52.216.24.4) port 80 (#0)
> GET /test.txt HTTP/1.1
> Host: test-bucket-for-condition-key-case-sensitivity.s3.amazonaws.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
[snip...]
< x-amz-server-side-encryption: AES256
< Accept-Ranges: bytes
< Content-Type: text/plain
< Server: AmazonS3
< Content-Length: 5
< 
test
liyun-li commented 1 year ago

Interesting! We can certainly take a look