Cloud Storage Bucket Exposure: S3, GCS, and Azure Blob Misconfigurations
Misconfigured cloud storage buckets expose sensitive data to the internet. Learn how to detect public S3, GCS, and Azure Blob Storage and lock them down.
Why cloud storage exposure is a top breach cause
Misconfigured cloud storage buckets are one of the most common causes of large-scale data breaches. The pattern is always the same: an S3 bucket, Google Cloud Storage bucket, or Azure Blob container is configured with public access, and sensitive data -- customer records, credentials, backups, source code, medical records -- is accessible to anyone with the URL.
These are not theoretical risks. Major breaches from public cloud storage have exposed hundreds of millions of records across government agencies, defence contractors, healthcare providers, and Fortune 500 companies. The data is often discovered by security researchers or, worse, by attackers who silently download everything before anyone notices.
How cloud storage access controls work
AWS S3
S3 has multiple layers of access control that interact (and sometimes conflict):
- Bucket policies -- JSON policies attached to the bucket that define who can access it
- ACLs (Access Control Lists) -- legacy mechanism that grants access to specific AWS accounts or to "Everyone" (public)
- Block Public Access settings -- account-level and bucket-level toggles that override policies and ACLs to prevent public access
- IAM policies -- identity-based policies that grant access to AWS users and roles
A bucket can be made public through any of these mechanisms. The most common mistakes:
// DANGEROUS: Allows anyone to read all objects
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket/*"
}
// DANGEROUS: Allows anyone to list and read
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::your-bucket",
"arn:aws:s3:::your-bucket/*"
]
}
Google Cloud Storage
GCS uses IAM and ACLs:
- Uniform bucket-level access -- recommended, uses IAM only
- Fine-grained access -- allows per-object ACLs
allUsers-- grants access to anyone on the internet (public)allAuthenticatedUsers-- grants access to anyone with a Google account (effectively public)
A bucket with allUsers as a member with the Storage Object Viewer role is fully public.
Azure Blob Storage
Azure uses:
- Container access level --
Private(no anonymous access),Blob(anonymous read for blobs), orContainer(anonymous read + list) - Shared Access Signatures (SAS) -- time-limited URLs with specific permissions
- Storage account settings -- account-level toggle for anonymous access
A container with access level set to Container allows anyone to list and download all blobs.
How to detect public buckets
AWS S3
# Check Block Public Access settings for a bucket
aws s3api get-public-access-block --bucket your-bucket-name
# Check the bucket policy
aws s3api get-bucket-policy --bucket your-bucket-name
# Check the bucket ACL
aws s3api get-bucket-acl --bucket your-bucket-name
# List all buckets and check each one
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 Public Access configured!"
done
AWS also provides Access Analyzer for S3 in the AWS Console, which identifies buckets accessible from outside your account.
Checking from the outside
# Try to list a bucket (public if this works)
curl -s https://your-bucket-name.s3.amazonaws.com/ | head
# Try to access a specific object
curl -s https://your-bucket-name.s3.amazonaws.com/test.txt
# GCS equivalent
curl -s https://storage.googleapis.com/your-bucket-name/
# Azure equivalent
curl -s "https://youraccount.blob.core.windows.net/your-container?restype=container&comp=list"
Automated scanning tools
- ScoutSuite -- multi-cloud security auditing
- Prowler -- AWS and Azure security assessment
- CloudSploit -- cloud security scanner
Searching for exposed buckets externally
Attackers use tools like GrayhatWarfare to search for public buckets by keyword. They also enumerate common bucket naming patterns:
yourcompany-backup
yourcompany-logs
yourcompany-data
yourcompany-dev
yourcompany-staging
yourcompany-assets
If your bucket name is guessable, and it is public, it will be found.
How to lock down cloud storage
AWS S3: Enable Block Public Access
This is the single most important step. Enable it at the account level to prevent any bucket from being made public:
# Account-level: block all public access for every bucket in the account
aws s3control put-public-access-block \
--account-id YOUR_ACCOUNT_ID \
--public-access-block-configuration \
BlockPublicAcls=true,\
IgnorePublicAcls=true,\
BlockPublicPolicy=true,\
RestrictPublicBuckets=true
# Bucket-level: block public access for a specific bucket
aws s3api put-public-access-block \
--bucket your-bucket-name \
--public-access-block-configuration \
BlockPublicAcls=true,\
IgnorePublicAcls=true,\
BlockPublicPolicy=true,\
RestrictPublicBuckets=true
Google Cloud Storage: Remove allUsers and allAuthenticatedUsers
# Check current IAM policy
gsutil iam get gs://your-bucket-name
# Remove public access
gsutil iam ch -d allUsers gs://your-bucket-name
gsutil iam ch -d allAuthenticatedUsers gs://your-bucket-name
# Enable uniform bucket-level access (recommended)
gsutil uniformbucketlevelaccess set on gs://your-bucket-name
At the organisation level, use an Organisation Policy to prevent public buckets:
gcloud resource-manager org-policies enable-enforce \
constraints/storage.publicAccessPrevention \
--organization=YOUR_ORG_ID
Azure Blob Storage: Disable anonymous access
# Disable anonymous access at the storage account level
az storage account update \
--name yourstorageaccount \
--resource-group your-rg \
--allow-blob-public-access false
# Set container access to private
az storage container set-permission \
--name your-container \
--account-name yourstorageaccount \
--public-access off
If you need public access for specific content
Some content (static website assets, public downloads, media files) legitimately needs to be public. In that case:
- Use a separate bucket for public content -- never mix public and private data
- Use a CDN (CloudFront, Cloud CDN, Azure CDN) in front of the bucket instead of making the bucket directly public
- Enable logging on the bucket to track access
- Use presigned URLs for temporary access to specific objects instead of making the entire bucket public
# AWS: Generate a presigned URL (expires in 1 hour)
aws s3 presign s3://your-bucket/file.pdf --expires-in 3600
Preventing future exposure
Infrastructure as Code
Define bucket configurations in Terraform, CloudFormation, or Pulumi with public access explicitly disabled:
# Terraform -- S3 bucket with public access blocked
resource "aws_s3_bucket_public_access_block" "example" {
bucket = aws_s3_bucket.example.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Automated policy enforcement
Use AWS Config rules, GCP Organisation Policies, or Azure Policy to automatically detect and remediate public buckets:
# AWS Config rule: flag any bucket that is publicly accessible
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "s3-bucket-public-read-prohibited",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}
}'
Regular audits
Even with guardrails, audit your cloud storage quarterly. Teams find creative ways to work around restrictions, and new services may create buckets with unexpected permissions. Tools like Shodan and GrayhatWarfare search for public buckets continuously -- you should too.
For a broader perspective on managing your cloud attack surface, see our guide on attack surface management.
How SurfaceScan helps
SurfaceScan discovers cloud storage buckets associated with your organisation through DNS enumeration, certificate analysis, and web content scanning. It tests each bucket for public accessibility and flags exposed storage as critical severity. Findings include which bucket is exposed, what access level is configured, and step-by-step remediation for your specific cloud provider -- so you can close the exposure before sensitive data is discovered by someone else.
Related articles
What is Attack Surface Management? A Complete Introduction
Attack surface management (ASM) helps organisations discover, monitor, and secure all internet-facing assets. Learn the ASM lifecycle and why continuous monitoring matters.
Exposed Database Ports: A Critical Security Finding You Must Fix Now
Database ports like MySQL 3306, PostgreSQL 5432, MongoDB 27017, and Redis 6379 exposed to the internet are a critical risk. Learn how to detect and secure them.
What Shodan Reveals About Your Infrastructure -- and What Attackers See
Shodan indexes every internet-connected device. Learn what information it exposes about your organisation, how attackers use it, and how to reduce your footprint.