Skip to content
HackIndex logo

HackIndex

S3 Bucket Discovery

1 min read May 24, 2026

S3 bucket names are globally unique and often predictable. Discovery happens before you have any credentials — you are looking for buckets that are publicly accessible or whose names leak useful information.

Certificate Transparency

Certificates issued for *.s3.amazonaws.com subdomains and custom domain CNAMEs often expose bucket names. Search crt.sh:

https://crt.sh/?q=%25.$DOMAIN

Look for entries where the common name or SAN matches an S3 pattern:

assets.example.com → CNAME → assets.example.com.s3.amazonaws.com

Any CNAME pointing to *.s3.amazonaws.com is a bucket name.

Google Dorks

site:s3.amazonaws.com "$DOMAIN"
site:s3.amazonaws.com "$COMPANY"
site:$DOMAIN filetype:pdf
inurl:s3.amazonaws.com "$COMPANY"

Also search for exposed content directly:

site:s3.amazonaws.com inurl:backup
site:s3.amazonaws.com inurl:dump
site:s3.amazonaws.com inurl:config

Passive DNS and Subdomain Enumeration

Run standard subdomain enumeration against the target domain. S3-backed subdomains resolve to AWS IP ranges and have s3.amazonaws.com CNAMEs.

┌──(kali㉿kali)-[~]
└─$ subfinder -d $DOMAIN -silent | httpx -silent -follow-redirects -title -status-code | grep -i s3
┌──(kali㉿kali)-[~]
└─$ amass enum -passive -d $DOMAIN | grep -i s3

Permutation Brute-Forcing

S3Scanner tests a wordlist of bucket names for existence and public access.

┌──(kali㉿kali)-[~]
└─$ pipx install s3scanner

Generate permutations from the target name:

┌──(kali㉿kali)-[~]
└─$ cat > buckets.txt <<EOF
$COMPANY
$COMPANY-backup
$COMPANY-dev
$COMPANY-staging
$COMPANY-prod
$COMPANY-assets
$COMPANY-static
$COMPANY-media
$COMPANY-uploads
$COMPANY-data
$COMPANY-logs
$COMPANY-internal
$COMPANY-public
$COMPANY-private
$COMPANY-files
$COMPANY-www
EOF
┌──(kali㉿kali)-[~]
└─$ s3scanner scan --buckets-file buckets.txt
[found] $COMPANY-backup - AuthUsers can read, Everyone can read
[found] $COMPANY-assets - Everyone can read
[not found] $COMPANY-dev
Explain command
--buckets-file File containing one bucket name per line.

Everyone can read = publicly accessible without credentials. AuthUsers = any authenticated AWS account can read — still exploitable.

DNS Brute-Force via S3 Endpoint

Direct bucket URL format: https://$BUCKET.s3.amazonaws.com

A 301 or 200 response means the bucket exists. A 403 means it exists but is not public. A 404 means it does not exist.

┌──(kali㉿kali)-[~]
└─$ curl -s -o /dev/null -w "%{http_code}" https://$BUCKET.s3.amazonaws.com
┌──(kali㉿kali)-[~]
└─$ while read bucket; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://$bucket.s3.amazonaws.com")
echo "$code $bucket"
done < buckets.txt | grep -v "^404"

403 is still a hit — it confirms the bucket exists even though it is not public. Note the name for authenticated enumeration later.

What to Do With a Found Bucket

  • 200 on https://$BUCKET.s3.amazonaws.com — bucket lists its contents without credentials. Proceed to enumeration.

  • 403 — bucket exists, private. Test with credentials during enumeration phase.

  • CNAME to s3.amazonaws.com returning NoSuchBucket — potential subdomain takeover. The bucket name is not claimed. Register it to capture traffic.

See S3 Bucket Enumeration and ACL Review for authenticated access.