critical8 min readLast updated May 27, 2026

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), or Container (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

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