Cloud Storage Buckets Exposed Publicly Without Access Controls

Critical Risk Infrastructure Security
aws-s3google-cloud-storageazure-blob-storagepublic-bucketsdata-exposureaccess-controlsbucket-policydata-breachcloud-security

What it is

A critical security vulnerability where cloud storage buckets (AWS S3, Google Cloud Storage, Azure Blob Storage) are configured with public read or write permissions, exposing sensitive data to unauthorized access. This misconfiguration allows anyone on the internet to list, read, or modify bucket contents, leading to data breaches, intellectual property theft, and compliance violations.

# VULNERABLE: S3 bucket with public access
resource "aws_s3_bucket" "vulnerable_data" {
  bucket = "myapp-data"
  
  # VULNERABLE: Public read access
  acl = "public-read"
}

resource "aws_s3_bucket_public_access_block" "vulnerable_data" {
  bucket = aws_s3_bucket.vulnerable_data.id
  
  # VULNERABLE: Public access allowed
  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

# VULNERABLE: Bucket policy allowing public access
resource "aws_s3_bucket_policy" "vulnerable_policy" {
  bucket = aws_s3_bucket.vulnerable_data.id
  
  policy = jsonencode({
    Statement = [{
      Effect = "Allow"
      Principal = "*"  # VULNERABLE: Anyone
      Action = "s3:GetObject"
      Resource = "${aws_s3_bucket.vulnerable_data.arn}/*"
    }]
  })
}
# SECURE: S3 bucket with blocked public access
resource "aws_s3_bucket" "secure_data" {
  bucket = "myapp-secure-data"
  
  # SECURE: No public ACL
}

# SECURE: Block all public access
resource "aws_s3_bucket_public_access_block" "secure_data" {
  bucket = aws_s3_bucket.secure_data.id
  
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# SECURE: Bucket policy with specific IAM role
resource "aws_s3_bucket_policy" "secure_policy" {
  bucket = aws_s3_bucket.secure_data.id
  
  policy = jsonencode({
    Statement = [
      {
        Effect = "Deny"
        Principal = "*"
        Action = "s3:*"
        Resource = [
          aws_s3_bucket.secure_data.arn,
          "${aws_s3_bucket.secure_data.arn}/*"
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      },
      {
        Effect = "Allow"
        Principal = {
          AWS = aws_iam_role.app_role.arn
        }
        Action = [
          "s3:GetObject",
          "s3:PutObject"
        ]
        Resource = "${aws_s3_bucket.secure_data.arn}/*"
      }
    ]
  })
}

💡 Why This Fix Works

The vulnerable configuration uses acl = 'public-read', disables Block Public Access settings, and uses Principal: '*' in the bucket policy, allowing anyone on the internet to access bucket contents. The secure version removes the public ACL, enables all Block Public Access settings, denies insecure transport, and restricts access to a specific IAM role instead of allowing public access.

Why it happens

AWS S3 buckets configured with public-read or public-read-write Access Control Lists (ACLs), granting everyone on the internet permission to list and read bucket objects. These overly permissive ACLs often result from misunderstanding AWS permissions or copy-pasting insecure configurations.

Root causes

Public ACLs on S3 Buckets

AWS S3 buckets configured with public-read or public-read-write Access Control Lists (ACLs), granting everyone on the internet permission to list and read bucket objects. These overly permissive ACLs often result from misunderstanding AWS permissions or copy-pasting insecure configurations.

Disabled Block Public Access Settings

AWS Block Public Access settings disabled at the account or bucket level, removing AWS's built-in protections against public bucket exposure. Without these safeguards, buckets can be made public through ACLs or bucket policies, even accidentally.

Wildcard Principal in Bucket Policies

S3 bucket policies that grant permissions to Principal: '*', allowing any AWS account or unauthenticated user to access bucket contents. These overly broad policies enable unrestricted data access without any authentication requirements.

AllUsers Permissions in Google Cloud Storage

GCS buckets granted allUsers or allAuthenticatedUsers IAM bindings, making bucket contents accessible to anyone on the internet or any authenticated Google account. These permissions are often added for temporary testing and forgotten.

Public Azure Blob Container Access Levels

Azure Blob Storage containers configured with 'Blob' (anonymous blob read) or 'Container' (anonymous container and blob list) access levels. These settings expose all blobs within containers to unauthenticated public internet access.

Fixes

1

Enable AWS Block Public Access

Enable Block Public Access settings at both the AWS account level and individual S3 bucket level. Configure all four settings (BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets) to prevent any public access configurations, providing defense-in-depth protection against accidental public exposure.

2

Remove Public ACLs from Buckets

Audit all S3 buckets and remove public-read and public-read-write ACL grants. Use AWS CLI commands like 'aws s3api get-bucket-acl' to identify public ACLs, then replace them with private ACLs. Configure bucket ownership controls to disable ACLs entirely in favor of bucket policies.

3

Replace Wildcard Principals with Specific Identities

Review all bucket policies and IAM policies for Principal: '*' entries. Replace wildcards with specific AWS account IDs, IAM role ARNs, or service principals. Use Condition blocks to further restrict access by IP address, VPC endpoint, or other contextual factors.

4

Use Pre-Signed URLs for Temporary Access

When legitimate public access is required, generate time-limited pre-signed URLs using AWS SDKs instead of making buckets or objects permanently public. Pre-signed URLs provide controlled, auditable, temporary access with automatic expiration.

5

Enable Logging and Versioning

Configure S3 server access logging and CloudTrail data events to monitor all bucket access and policy changes. Enable S3 versioning to maintain object history and protect against accidental or malicious deletions. Use these logs to detect unauthorized access attempts and policy modifications.

Detect This Vulnerability in Your Code

Sourcery automatically identifies cloud storage buckets exposed publicly without access controls and many other security issues in your codebase.