Cloud storage misconfigurations are one of the most reliably found vulnerabilities in external attack surface assessments. S3 buckets, Google Cloud Storage buckets, and Azure Blob containers accidentally made public have caused some of the largest data breaches of the past decade. Understanding how these exposures happen, how attackers find them, and how to audit your own storage is essential cloud security knowledge.

How Buckets Become Public

Public cloud storage buckets rarely start public intentionally. The most common causes:

How Attackers Find Exposed Buckets

Attackers use several techniques to discover public buckets associated with a target:

Bucket Name Guessing

AWS S3 bucket names are globally unique and often follow predictable patterns. Tools scan common naming conventions:

company-name-backup
company-name-dev
company-name-staging
company-name-data
company-name-logs
company-name-assets
company-name.com

Tools like s3scanner, bucket_finder, and AWSBucketDump automate this enumeration, checking thousands of name variations in minutes.

Certificate Transparency Logs

Certificate Transparency (CT) logs record every TLS certificate issued. Attackers query CT logs for subdomains of a target domain — subdomains like assets.company.com, media.company.com, or cdn.company.com that point to S3 buckets are visible in CT log searches. Services like crt.sh make this trivial.

DNS Records and CNAME Chains

If a bucket is configured as a website endpoint and a CNAME points to it, the bucket URL is visible in DNS records. Shodan and Censys index bucket endpoints as part of their internet-wide scans.

Notable Breaches

Capital One (2019) — 106 million customer records exposed. The attacker exploited an SSRF vulnerability to access the EC2 metadata service and retrieve IAM credentials, then used those credentials to download data from an S3 bucket. While not a direct misconfiguration, the bucket's permissions allowed the compromised role to read it.

Twitch (2021) — 125GB of internal data including source code was leaked. While the root cause was a server misconfiguration, inadequate access segmentation meant a single compromise exposed massive amounts of internal data.

GoDaddy (multiple incidents) — Multiple incidents involving misconfigured S3 buckets exposed customer data and configuration files.

Thousands of unnamed companies — Reseachers report finding hundreds of exposed buckets containing customer databases, internal documents, source code, and API keys every month.

Auditing Your S3 Buckets

# List all buckets
aws s3api list-buckets --query 'Buckets[].Name'

# Check public access block settings for each bucket
aws s3api get-public-access-block --bucket BUCKET_NAME

# Check bucket ACL
aws s3api get-bucket-acl --bucket BUCKET_NAME

# Check bucket policy
aws s3api get-bucket-policy --bucket BUCKET_NAME

# Check if static website hosting is enabled
aws s3api get-bucket-website --bucket BUCKET_NAME

# List all buckets and their public access block status (batch audit)
for bucket in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do
    echo "=== $bucket ==="
    aws s3api get-public-access-block --bucket $bucket 2>/dev/null || echo "No block settings"
done

Auditing GCS and Azure

# Google Cloud Storage — list buckets and check IAM
gsutil ls
gsutil iam get gs://BUCKET_NAME
# Look for allUsers or allAuthenticatedUsers with storage.objectViewer

# Azure Blob Storage — check container access level
az storage container list --account-name ACCOUNT_NAME
az storage container show-permission --name CONTAINER_NAME --account-name ACCOUNT_NAME
# Public access level "blob" or "container" means publicly readable

Enabling Block Public Access

# AWS — enable block public access at the account level (recommended)
aws s3control put-public-access-block   --account-id YOUR_ACCOUNT_ID   --public-access-block-configuration     BlockPublicAcls=true,IgnorePublicAcls=true,    BlockPublicPolicy=true,RestrictPublicBuckets=true

# Per-bucket
aws s3api put-public-access-block   --bucket BUCKET_NAME   --public-access-block-configuration     BlockPublicAcls=true,IgnorePublicAcls=true,    BlockPublicPolicy=true,RestrictPublicBuckets=true

Account-level Block Public Access overrides individual bucket settings. Enable it at the account level unless you have a specific, documented requirement for public buckets.

Bucket Policies vs ACLs

AWS recommends disabling ACLs entirely for most use cases and using bucket policies exclusively. ACLs are a legacy access control mechanism that can interact with bucket policies in confusing ways. Enable "bucket owner enforced" mode in Object Ownership settings to disable ACLs:

aws s3api put-bucket-ownership-controls   --bucket BUCKET_NAME   --ownership-controls Rules=[{ObjectOwnership=BucketOwnerEnforced}]

Monitoring with CloudTrail and S3 Server Access Logs

Enable CloudTrail data events for S3 to log all GetObject and PutObject operations. This creates an audit trail that is critical for breach investigation. Enable S3 server access logging as a complementary measure — it captures requests from users who access objects before CloudTrail processes them.

Set up CloudWatch alerts for: unexpected public access re-enabled events, large-volume GetObject requests from unexpected IPs, and Cross-Account access to your buckets.