How to Find All Publicly Accessible S3 Buckets in Your AWS Account
- Learn how to sync your AWS S3 data with CloudQuery.
- Understand the risks associated with public S3 buckets.
- Run queries to identify publicly accessible buckets using CloudQuery.
What is CloudQuery? #
How to sync your AWS Cloud Data with CloudQuery #
- Sign Up for CloudQuery Start by creating a CloudQuery account to get started.
- Set Up Your Sync Configure a new sync using the AWS Source Integration. Make sure you have read-only access to your AWS account to enable data syncing.Configure a new sync using the AWS Source Integration. Make sure you have read-only access to your AWS account to enable data syncing. Refer to the authentication guide for details. For this, you will need to sync all the following S3 data tables:
tables: [ "aws_s3_buckets", "aws_s3_bucket_policies", "aws_s3_bucket_public_access_blocks", "aws_s3_bucket_grants", "aws_s3_access_points" ]
- Run Your Data Sync Click the “Run Sync” button to pull your AWS data into CloudQuery. Once synced, you can query and analyze your EC2 inventory.
Analyzing your Data #
Find All S3 Buckets with Public Policies #
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
p.policy_json AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_policies AS p
ON
b.arn = p.bucket_arn
WHERE
JSONExtractString(p.policy_json, 'Statement[0].Principal') = '*'
OR JSONExtractString(p.policy_json, 'Statement[0].Effect') = 'Allow';
Find S3 Buckets with Public Grants #
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
g.permission AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_grants AS g
ON
b.arn = g.bucket_arn
WHERE
g.grantee_type IN ('AllUsers', 'AuthenticatedUsers');
Find S3 Buckets with Disabled Public Access Blocks #
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
pab.public_access_block_configuration AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_public_access_blocks AS pab
ON
b.arn = pab.bucket_arn
WHERE
JSONExtractBool(pab.public_access_block_configuration, 'BlockPublicAcls') = false
OR JSONExtractBool(pab.public_access_block_configuration, 'BlockPublicPolicy') = false;
How to Find All Publicly Accessible S3 Buckets in Your AWS Account #
-- Query to find all publicly accessible S3 buckets
SELECT *
FROM
(
-- Extract buckets with overly permissive bucket policies
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
'policy' AS access_type,
p.policy_json AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_policies AS p
ON
b.arn = p.bucket_arn
WHERE
JSONExtractString(p.policy_json, 'Statement[0].Principal') = '*' OR
JSONExtractString(p.policy_json, 'Statement[0].Effect') = 'Allow'
) AS policy_buckets
UNION ALL
SELECT *
FROM
(
-- Extract buckets with public grants
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
'grant' AS access_type,
g.permission AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_grants AS g
ON
b.arn = g.bucket_arn
WHERE
g.grantee_type IN ('AllUsers', 'AuthenticatedUsers')
) AS grant_buckets
UNION ALL
SELECT *
FROM
(
-- Extract buckets with disabled public access blocks
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn,
'public_access_block' AS access_type,
pab.public_access_block_configuration AS access_details
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_public_access_blocks AS pab
ON
b.arn = pab.bucket_arn
WHERE
JSONExtractBool(pab.public_access_block_configuration, 'BlockPublicAcls') = false OR
JSONExtractBool(pab.public_access_block_configuration, 'BlockPublicPolicy') = false
) AS pab_buckets
ORDER BY bucket_name;
Beyond Public Access: Other Key S3 Security Queries #
Buckets Without Encryption Enabled #
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_encryption_rules AS e
ON
b.arn = e.bucket_arn
WHERE
e.bucket_arn IS NULL;
List Buckets with No Object Lock Configurations #
SELECT
b.name AS bucket_name,
b.arn AS bucket_arn
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_object_lock_configurations AS olc
ON
b.arn = olc.bucket_arn
WHERE
olc.bucket_arn IS NULL;
List Buckets with Expired or No Lifecycle Rules #
SELECT
b.nameAS bucket_name,
b.arn AS bucket_arn
FROM
aws_s3_buckets AS b
LEFT JOIN
aws_s3_bucket_lifecycles AS lc
ON
b.arn = lc.bucket_arn
WHERE
lc.bucket_arn IS NULL OR lc.expiration IS NOT NULL;
Wrap Up #
FAQs #
Why is it important to check for publicly accessible S3 buckets? #
What’s the difference between bucket policies, grants, and public access blocks? #
- Bucket Policies: Define permissions at the bucket level, specifying who can access the bucket and what actions they can take.
- Grants: Set permissions for specific users or groups, often at the object level.
- Public Access Blocks: Provide a high-level control to restrict or block public access to buckets, overriding other permissions.
How can I ensure all my S3 buckets are encrypted? #
What should I do if I find a publicly accessible S3 bucket? #
- Review the bucket’s permissions to understand why it’s accessible.
- Update bucket policies to restrict access.
- Enable public access blocks to enforce restrictions at a higher level.
- Notify your team and monitor logs for potential unauthorized access.
Written by Joe Karlsson
Joe Karlsson (He/They) is an Engineer turned Developer Advocate (and massive nerd). Joe empowers developers to think creatively when building applications, through demos, blogs, videos, or whatever else developers need.