turbot/steampipe-mod-aws-compliance

Control: 3 S3 buckets should prohibit public write access

Description

This control checks whether your S3 buckets allow public write access by evaluating the Block Public Access settings, the bucket policy, and the bucket access control list (ACL).

It does not check for write 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

  1. Open the Amazon S3 console.
  2. Choose the name of the bucket identified in the finding.
  3. Choose Permissions and then choose Public access settings.
  4. Choose Edit, select all four options, and then choose Save.
  5. If prompted, enter confirm and then choose Confirm.

Usage

Run the control in your terminal:

powerpipe control run aws_compliance.control.foundational_security_s3_3

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run aws_compliance.control.foundational_security_s3_3 --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' = 'WRITE_ACP'
or grants ->> 'Permission' = 'WRITE'
)
), write_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:put%'
or action ilike 's3:delete%'
or action ilike 's3:create%'
or action ilike 's3:update%'
or action ilike 's3:replicate%'
or action ilike 's3:restore%'
)
)
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 bucket_policy_is_public and p.name is null then 'ok'
else 'alarm'
end status,
case
when (block_public_acls or a.name is null ) and not bucket_policy_is_public then b.title || ' not publicly writable.'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and block_public_policy) then b.title || ' not publicly writable.'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and p.name is null) then b.title || ' not publicly writable.'
else b.title || ' publicly writable.'
end reason
, b.region, b.account_id
from
aws_s3_bucket as b
left join public_acl as a on b.name = a.name
left join write_access_policy as p on b.name = p.name;

Tags