Control: 2 S3 buckets should prohibit public read access
Description
This control checks whether your S3 buckets allow public read access by evaluating the Block Public Access settings, the bucket policy, and the bucket access control list (ACL).
Unless you explicitly require everyone on the internet to be able to write to your S3 bucket, you should ensure that your S3 bucket is not publicly writable.
It does not check for read access to the bucket by internal principals, such as IAM roles. You should ensure that access to the bucket is restricted to authorized principals only.
Remediation
- Open the Amazon S3 console.
- Choose the name of the bucket identified in the finding.
- Choose Permissions and then choose Public access settings.
- Choose Edit, select all four options, and then choose Save.
- If prompted, enter
confirm
and then choose Confirm.
Usage
Run the control in your terminal:
powerpipe control run aws_compliance.control.foundational_security_s3_2
Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run aws_compliance.control.foundational_security_s3_2 --share
SQL
This control uses a named query:
with public_acl as ( select distinct name from aws_s3_bucket, jsonb_array_elements(acl -> 'Grants') as grants where (grants -> 'Grantee' ->> 'URI' = 'http://acs.amazonaws.com/groups/global/AllUsers' or grants -> 'Grantee' ->> 'URI' = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers') and ( grants ->> 'Permission' = 'FULL_CONTROL' or grants ->> 'Permission' = 'READ_ACP' or grants ->> 'Permission' = 'READ' ) ),read_access_policy as ( select distinct name from aws_s3_bucket, jsonb_array_elements(policy_std -> 'Statement') as s, jsonb_array_elements_text(s -> 'Action') as action where s ->> 'Effect' = 'Allow' and ( s -> 'Principal' -> 'AWS' = '["*"]' or s ->> 'Principal' = '*' ) and ( action = '*' or action = '*:*' or action = 's3:*' or action ilike 's3:get%' or action ilike 's3:list%' ))select b.arn as resource, case when (block_public_acls or a.name is null) and not bucket_policy_is_public then 'ok' when (block_public_acls or a.name is null) and (bucket_policy_is_public and block_public_policy) then 'ok' when (block_public_acls or a.name is null) and (bucket_policy_is_public and p.name is null) then 'ok' else 'alarm' end as status, case when (block_public_acls or a.name is null) and not bucket_policy_is_public then b.title || ' not publicly readable.' when (block_public_acls or a.name is null) and (bucket_policy_is_public and block_public_policy) then b.title || ' not publicly readable.' when (block_public_acls or a.name is null) and (bucket_policy_is_public and p.name is null) then b.title || ' not publicly readable.' else b.title || ' publicly readable.' end as reason , b.region, b.account_idfrom aws_s3_bucket as b left join public_acl as a on b.name = a.name left join read_access_policy as p on b.name = p.name;