S3 buckets should not be publicly readable¶
Description¶
S3 buckets should not be publicly readable. A bucket with a public ACL or bucket policy is exposed to the entire internet if all block public access settings are disabled at the resource and account level. This poses a critical security vulnerability, as any AWS user or anonymous user can access the data in the bucket.
Remediation Steps¶
AWS Console¶
Navigate to S3.
Select the S3 bucket.
Select Permissions > Access Control List.
In Public access, select Everyone and uncheck:
List objects
Write objects
Read bucket permissions
Write bucket permissions
Click Save.
Select Bucket Policy.
Navigate to S3.
In the left navigation, select Block public access (account settings).
Click Edit.
Check the Block all public access checkbox.
Click Save Changes.
Enter
confirm
and click confirm.
AWS CLI¶
To make an S3 bucket not publicly accessible:
aws s3api put-bucket-acl \
--bucket fugue-bucket-example --acl private
aws s3api put-public-access-block \
--bucket fugue-bucket-example \
--public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
To enable block public access settings at the account level:
aws s3control put-public-access-block \
--account-id 123456789012 \
--public-access-block-configuration '{"BlockPublicAcls": true, "IgnorePublicAcls": true, "BlockPublicPolicy": true, "RestrictPublicBuckets": true}'
Terraform¶
Ensure that the aws_s3_bucket
acl
field does NOT contain EITHER of the following:“public-read”
“public-read-write”
Ensure that the
grant
block does NOT contain BOTH an invaliduri
andpermissions
field:Invalid
uri
:Invalid
permissions
:“READ”
“FULL_CONTROL”
“READ_ACP”
If a bucket policy is defined in the bucket’s
policy
field, ensure the JSON document does NOT contain BOTH an invalid principal, an invalid action, and an invalid effect:Invalid principals:
"Principal": { "AWS": "*" }
"Principal": "*"
Invalid actions:
"*"
"s3:*"
"s3:List*"
"s3:Get*"
"s3:ListBucket*"
"s3:GetObject*"
"s3:ListBucket"
"s3:ListBucketVersions"
"s3:ListBucketMultipartUploads"
"s3:GetObject"
"s3:GetObjectVersion"
"s3:GetObjectTorrent"
Invalid effect:
"Effect": "Allow"
If a bucket policy as defined as an aws_s3_bucket_policy, ensure the JSON document in the
policy
field does NOT contain BOTH an invalid principal, an invalid action, and an invalid effect, as listed aboveWhile a aws_s3_bucket_public_access_block is not required for the bucket, it’s highly recommended. Ensure the following aws_s3_bucket_public_access_block fields are all set to
true
:block_public_acls
block_public_policy
ignore_public_acls
restrict_public_buckets
You can enable block public access settings for all buckets in your account by using a aws_s3_account_public_access_block. Ensure the following fields are all set to
true
:block_public_acls
block_public_policy
ignore_public_acls
restrict_public_buckets
Example Configuration¶
# Compliant ACL
resource "aws_s3_bucket" "b" {
acl = "private"
# other required fields here
}
# Compliant grant
resource "aws_s3_bucket" "bucket" {
bucket = "mybucket"
grant {
id = data.aws_canonical_user_id.current_user.id
type = "CanonicalUser"
permissions = ["FULL_CONTROL"]
}
# other required fields here
}
# Compliant bucket policy
resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
# other required fields here
}
resource "aws_s3_bucket_policy" "b" {
bucket = aws_s3_bucket.b.id
policy = jsonencode({
Version = "2012-10-17"
Id = "MYBUCKETPOLICY"
Statement = [
{
Sid = "IPAllow"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.b.arn,
"${aws_s3_bucket.b.arn}/*",
]
Condition = {
NotIpAddress = {
"aws:SourceIp" = "8.8.8.8/32"
}
}
},
]
})
# other required fields here
}
# Compliant public access block - single bucket
resource "aws_s3_bucket" "b" {
# other required fields here
}
resource "aws_s3_bucket_public_access_block" "private" {
bucket = "${aws_s3_bucket.b.id}"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Compliance public access block - ALL buckets
resource "aws_s3_account_public_access_block" "main" {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}