Description

Ensure that every Amazon S3 bucket has a bucket policy that denies uploads made over insecure (HTTP) transport. The policy must contain a Deny statement for the action s3:PutObject, s3:* or * that applies when the condition key aws:SecureTransport is false. Using s3:* or * is recommended, so that only HTTPS (TLS) requests are accepted for every operation. Buckets without a bucket policy, or whose policy has no such statement, accept plain HTTP requests.

Rationale

Requests sent over plain HTTP expose object data and authentication details to eavesdropping and man-in-the-middle attacks. Pre-signed URLs captured in transit can be replayed to read or change data, and traffic can be intercepted or altered. A bucket policy that denies requests when aws:SecureTransport is false forces all clients to use HTTPS and protects the confidentiality and integrity of the data in transit.

Impact

  • Ensures all access to the bucket is encrypted in transit with TLS

  • Protects pre-signed URLs and request credentials from interception

  • Clients or applications that still use plain HTTP (for example, the S3 website endpoint over HTTP) will receive Access Denied errors and must be switched to HTTPS

Default Value

A new S3 bucket has no bucket policy, so requests over HTTP are not denied.

Pre-Requisites

  • IAM permissions: s3:ListAllMyBuckets, s3:GetBucketPolicy and s3:PutBucketPolicy

  • Confirmation that all applications and users access the bucket over HTTPS

  • A copy of the existing bucket policy, because the new statement must be added to it rather than replace it

Remediation

Test Plan

Console:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon S3 console and select Buckets.

  3. Select a bucket and open the Permissions tab.

  4. In the Bucket policy section, check for a statement that:

    • has "Effect": "Deny",

    • has an Action of s3:*, * or s3:PutObject, and

    • has the condition "Bool": { "aws:SecureTransport": "false" }.

  5. Repeat for each bucket.

  6. If the bucket has no policy, or no such statement exists, follow the implementation steps.

CLI:

List all buckets:

aws s3api list-buckets --query "Buckets[].Name"

Show the bucket policy of a bucket:

aws s3api get-bucket-policy --bucket <BUCKET_NAME> --query Policy --output text

A bucket fails if the command returns a NoSuchBucketPolicy error, or if the policy has no Deny statement with an Action of s3:*, * or s3:PutObject and the condition aws:SecureTransport set to false.

Implementation Steps

Console:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon S3 console and select the bucket.

  3. Open the Permissions tab and choose Edit in the Bucket policy section.

  4. Add the following statement to the Statement list, keeping any existing statements (if the bucket has no policy, paste the full policy shown in the CLI step below):

    • {"Sid": "DenyInsecureTransport", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": ["arn:aws:s3:::<BUCKET_NAME>", "arn:aws:s3:::<BUCKET_NAME>/*"], "Condition": {"Bool": {"aws:SecureTransport": "false"}}}

  5. Choose Save changes.

  6. Repeat for each affected bucket.

CLI:

The command below replaces the whole bucket policy, so if the bucket already has a policy, first add the DenyInsecureTransport statement to the existing statements from the Test Plan output. The statement also covers the bucket itself, not only its objects. Save the following as policy.json:

{"Version": "2012-10-17", "Statement": [{"Sid": "DenyInsecureTransport", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": ["arn:aws:s3:::<BUCKET_NAME>", "arn:aws:s3:::<BUCKET_NAME>/*"], "Condition": {"Bool": {"aws:SecureTransport": "false"}}}]}

Apply the policy to the bucket:

aws s3api put-bucket-policy --bucket <BUCKET_NAME> --policy file://policy.json

Backout Plan

Before making changes, save the current bucket policy:

aws s3api get-bucket-policy --bucket <BUCKET_NAME> --query Policy --output text > policy-backup.json

To roll back:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon S3 console, select the bucket and open the Permissions tab.

  3. Choose Edit in the Bucket policy section.

  4. Remove the DenyInsecureTransport statement, or paste back the saved policy. If the bucket had no policy before, choose Delete instead.

  5. Choose Save changes.

CLI:

Restore the saved policy:

aws s3api put-bucket-policy --bucket <BUCKET_NAME> --policy file://policy-backup.json

If the bucket had no policy before, delete the policy instead:

aws s3api delete-bucket-policy --bucket <BUCKET_NAME>

Note: rolling back allows requests over plain HTTP again.

Reference