S3Scanner: Complete Guide to Amazon S3 Bucket Discovery and Security Assessment Using Kali Linux

S3Scanner: Complete Guide to Amazon S3 Bucket Discovery and Security Assessment Using Kali Linux

S3Scanner is an open-source reconnaissance tool, originally created by Dan Salmon (sa7mon), purpose-built for discovering and auditing Amazon S3 buckets (and S3-API-compatible storage such as DigitalOcean Spaces, Wasabi, and Backblaze B2). It is one of the most widely used tools in the bug bounty and penetration testing community specifically for identifying misconfigured, publicly accessible cloud storage — a vulnerability class responsible for numerous high-profile data breaches over the years (exposed customer PII, source code, credentials, backups, and internal documents).

Unlike CloudBrute, which enumerates across many cloud providers and resource types, S3Scanner is laser-focused on S3 buckets, and offers deeper bucket-level inspection once a bucket name is known or guessed:

  • Bucket existence check — determines whether a given bucket name exists at all.
  • Permission enumeration — checks specific ACL permissions: READ (list objects), WRITE (upload objects), READ_ACP (read bucket ACL), WRITE_ACP (modify bucket ACL), and FULL_CONTROL.
  • Bucket dumping — downloads the full contents of a bucket if READ access is available.
  • Multi-region support — automatically detects the correct AWS region a bucket lives in.
  • Compatible storage providers — can also test buckets hosted on DigitalOcean Spaces, Google Cloud Storage (S3-compatible endpoints), and other S3-API-compatible services.

S3Scanner is typically used as a follow-up tool after a bucket name has been discovered — either through a wordlist-based brute-force scan (its own built-in scan mode), OSINT (e.g., found in JavaScript source code, GitHub commits, or DNS records), or the output of a tool like CloudBrute.

Installation

Method 1: Go install (recommended, S3Scanner v3+ is written in Go)

sudo apt install golang-go -y
go install github.com/sa7mon/s3scanner@latest
export PATH=$PATH:$(go env GOPATH)/bin

Method 2: Download pre-compiled binary from GitHub Releases

wget https://github.com/sa7mon/S3Scanner/releases/latest/download/s3scanner_linux_amd64.tar.gz
tar -xzf s3scanner_linux_amd64.tar.gz
chmod +x s3scanner
sudo mv s3scanner /usr/local/bin/

Method 3: Build from source

git clone https://github.com/sa7mon/S3Scanner.git
cd S3Scanner
go build .
sudo mv s3scanner /usr/local/bin/

Method 4 (legacy Python version, for older references):

git clone https://github.com/sa7mon/S3Scanner.git
cd S3Scanner
pip install -r requirements.txt
python3 s3scanner.py --help

Verify installation:

s3scanner version

Expected output:

s3scanner version 3.1.0

Syntax

s3scanner [command] [flags]

Main subcommands:

s3scanner scan   -f <bucket_list_file>     # Scan a list of bucket names
s3scanner dump   -b <bucket_name>            # Dump contents of a specific bucket

Complete Command-Line Options Reference

Global Commands

s3scanner scan            Scan one or more bucket names for existence and permissions
s3scanner dump             Download ("dump") the contents of an accessible bucket
s3scanner version          Print version information
s3scanner help              Display help menu

scan Subcommand Flags

-f, --bucket-file FILE          File containing a list of bucket names to check (one per line)
-b, --bucket NAME                Scan a single bucket name directly
--json                          Output results in JSON format
--include-closed                  Include non-existent/closed buckets in output (default: only report found buckets)
--threads N                       Number of concurrent scanning threads (default: 10)
--endpoint-url URL                  Use a custom S3-compatible endpoint (e.g., DigitalOcean Spaces)
--provider {aws,digitalocean,gcp,dreamhost,linode}   Target a specific S3-compatible provider
--enumerate-ips                    Attempt to resolve and display associated IP addresses
--out FILE                        Save results to a specified output file
-v, --verbose                     Enable verbose logging

dump Subcommand Flags

-b, --bucket NAME                Name of the bucket to dump
-o, --dump-dir DIR                 Local directory to save downloaded objects (default: ./buckets/)
--threads N                       Number of concurrent download threads (default: 10)
--endpoint-url URL                  Custom S3-compatible endpoint for the dump operation
--max-size SIZE                    Skip files larger than this size (e.g., 100MB)
--dry-run                        List objects that would be downloaded without actually downloading them

Miscellaneous

-h, --help                      Show help for the given command
--version                       Show version and exit

Basic Usage

s3scanner scan -f bucket_names.txt

Expected console output:

$ s3scanner scan -f bucket_names.txt

s3scanner v3.1.0 - Scanning 250 candidate bucket names...

[bucket_exists]   acme-uploads          | region: us-east-1  | perms: [READ, LIST]
[bucket_exists]   acme-backups-2025      | region: eu-west-1  | perms: [READ, WRITE, LIST]  <-- Critical!
[bucket_not_exist] acme-test-storage
[bucket_exists]   acme-static-assets     | region: us-east-1  | perms: []  (exists but no permissions)

Scan complete: 3 buckets found (1 with WRITE access), 247 not found, in 38 seconds

Practical Examples with Output

Example 1: Scan a wordlist of candidate bucket names

s3scanner scan -f candidates.txt
Scanning 500 bucket names...
[bucket_exists] acme-logs | region: us-east-1 | perms: [READ]
Scan complete: 1 bucket found, 499 not found

Example 2: Scan a single known/guessed bucket name

s3scanner scan -b acme-prod-backups
[bucket_exists] acme-prod-backups | region: us-west-2 | perms: [READ, READ_ACP]
Scan complete: bucket exists and is partially accessible

Example 3: Output results in JSON for downstream processing

s3scanner scan -f candidates.txt --json --out results.json
Scan complete: results written in JSON format to results.json
{"bucket":"acme-logs","exists":true,"region":"us-east-1","permissions":["READ"]}

Example 4: Increase thread count for faster scanning of a large wordlist

s3scanner scan -f big_wordlist.txt --threads 50
Scanning 10,000 bucket names with 50 threads...
Scan complete: 12 buckets found in 2m14s (vs ~11m at default 10 threads)

Example 5: Dump the contents of a bucket with READ access

s3scanner dump -b acme-prod-backups -o /home/kali/loot/acme-prod-backups
[dump] Bucket: acme-prod-backups
[dump] Listing objects... 342 objects found (1.2 GB total)
[dump] Downloading to /home/kali/loot/acme-prod-backups/
[dump] Progress: 342/342 objects downloaded
[dump] Dump complete.

Example 6: Dry-run a dump to preview what would be downloaded

s3scanner dump -b acme-prod-backups --dry-run
[dump] DRY RUN - no files will be downloaded
[dump] Would download 342 objects (1.2 GB total):
  backups/2026-06-01/database.sql.gz (450 MB)
  backups/2026-06-01/config.yaml (2 KB)
  ...

Example 7: Skip large files during a dump to save disk space

s3scanner dump -b acme-prod-backups --max-size 50MB -o /home/kali/loot/
[dump] Skipping 4 files larger than 50MB
[dump] Downloading 338 objects (89 MB total)
[dump] Dump complete.

Example 8: Scan against DigitalOcean Spaces instead of AWS S3

s3scanner scan -f candidates.txt --provider digitalocean --endpoint-url https://nyc3.digitaloceanspaces.com
Provider: digitalocean
Endpoint: https://nyc3.digitaloceanspaces.com
[bucket_exists] acme-cdn-assets | perms: [READ]
Scan complete: 1 Space found

Example 9: Include closed/non-existent buckets in the output for a full audit trail

s3scanner scan -f candidates.txt --include-closed --out full-audit.txt
Scan complete: 500 total results written (3 found, 497 not found) to full-audit.txt

Example 10: Verbose mode for debugging a scan

s3scanner scan -b acme-test -v
[VERBOSE] Resolving DNS for acme-test.s3.amazonaws.com...
[VERBOSE] DNS resolved to 52.216.x.x
[VERBOSE] Sending HEAD request...
[VERBOSE] Response: 403 Forbidden (bucket exists, access denied)
[bucket_exists] acme-test | region: unknown | perms: []

Example 11: Chain CloudBrute output directly into S3Scanner

cloudbrute -d acme.com -k acme -w storage_small.txt -m storage -C aws -o cloudbrute-out.txt
grep "s3.amazonaws.com" cloudbrute-out.txt | cut -d'-' -f1 > s3-candidates.txt
s3scanner scan -f s3-candidates.txt
[+] Extracted 6 candidate bucket names from CloudBrute output
Scan complete: 4 buckets confirmed to exist, 2 with READ access

Example 12: Enumerate associated IP addresses for discovered buckets

s3scanner scan -f candidates.txt --enumerate-ips
[bucket_exists] acme-cdn | region: us-east-1 | IPs: [52.216.128.45, 52.216.129.10] | perms: [READ]
Scan complete: 1 bucket found with IP resolution data

16.5.7 Common Use Cases

  • Bug bounty hunting: Discovering exposed S3 buckets that leak sensitive data, often a high-value, easy-to-report finding.
  • Penetration testing: Confirming and demonstrating impact of publicly writable or readable buckets identified during reconnaissance.
  • Data breach investigation: Quickly determining the scope of exposure once a leaked bucket name is identified in the wild (e.g., referenced in a paste site or leaked source code).
  • Continuous cloud storage monitoring: Scheduling regular scans of known company-related bucket name patterns to catch new exposures early.
  • Incident response: Confirming whether a specific bucket suspected of being involved in an incident is (or was) publicly accessible.

16.5.8 Automation with Bash

Automated bucket-name generation and scan pipeline:

#!/bin/bash
# s3scanner-auto.sh
# Generates permutations of a company name and scans them all

COMPANY="acme"
SUFFIXES=("backup" "backups" "dev" "prod" "staging" "assets" "static" "uploads" "logs" "data" "files" "media" "cdn" "internal" "public" "private" "test" "archive")
CANDIDATES_FILE="/tmp/acme-s3-candidates.txt"

> "$CANDIDATES_FILE"
for suffix in "${SUFFIXES[@]}"; do
    echo "${COMPANY}-${suffix}" >> "$CANDIDATES_FILE"
    echo "${COMPANY}${suffix}" >> "$CANDIDATES_FILE"
    echo "${suffix}-${COMPANY}" >> "$CANDIDATES_FILE"
done

echo "[+] Generated $(wc -l < "$CANDIDATES_FILE") candidate bucket names"
s3scanner scan -f "$CANDIDATES_FILE" --json --out "/home/kali/reports/s3scan-$(date +%F).json"
echo "[+] Scan complete. Results saved."

Automated dump of all discovered READ-accessible buckets:

#!/bin/bash
# s3scanner-auto-dump.sh
# Parses a JSON scan result and dumps every bucket with READ access

RESULTS_FILE="$1"
DUMP_BASE="/home/kali/loot/s3-dumps-$(date +%F)"

if [ -z "$RESULTS_FILE" ]; then
    echo "Usage: $0 <s3scanner_results.json>"
    exit 1
fi

mkdir -p "$DUMP_BASE"
jq -r 'select(.permissions[] == "READ") | .bucket' "$RESULTS_FILE" | while read -r bucket; do
    echo "[+] Dumping bucket: $bucket"
    s3scanner dump -b "$bucket" -o "$DUMP_BASE/$bucket" --max-size 200MB
done
echo "[+] All READ-accessible buckets dumped to $DUMP_BASE"

16.5.9 Tips and Best Practices

  • Always confirm scope authorization before dumping bucket contents — even publicly accessible buckets may contain data outside the agreed engagement scope, and downloading data has legal implications distinct from merely confirming exposure.
  • Use --dry-run before every dump operation to preview size and object count, avoiding accidental multi-gigabyte downloads on limited storage/bandwidth.
  • Combine S3Scanner with CloudBrute for name generation, and with OSINT sources (GitHub, JS source maps, Wayback Machine) for additional candidate bucket names.
  • Use --max-size during dumps to prioritize smaller configuration/credential files over large binary backups, then follow up selectively on large files if needed.
  • When reporting a finding, capture screenshots or logs of the perms output (READ/WRITE/READ_ACP) — the specific permission set materially changes the severity rating of the finding.
  • Rotate/randomize scan timing and thread counts (--threads) when testing against providers known to have aggressive rate-limiting or bot-detection on their storage endpoints.

Troubleshooting

IssueCauseResolution
All buckets report bucket_not_existIncorrect bucket naming convention or region issueVerify naming pattern against target’s known convention; try --enumerate-ips for extra detail
dump command fails with AccessDeniedBucket permissions changed since scan, or scan misreported READ accessRe-run s3scanner scan -b <bucket> to confirm current permissions before retrying dump
Scan is very slow on large wordlistsThread count too lowIncrease --threads (e.g., --threads 50 or higher, balanced against network limits)
JSON output file is empty--include-closed not set and no buckets were foundConfirm candidate list quality, or add --include-closed to verify the scan actually ran
DigitalOcean/Spaces scan returns no resultsWrong --endpoint-url region subdomainVerify the correct regional endpoint (e.g., nyc3, sgp1, ams3) for the target Space
dump stalls on specific large filesNetwork timeout on large objectsUse --max-size to skip oversized objects, or increase client-side timeout settings

References

  • Official GitHub Repository: https://github.com/sa7mon/S3Scanner
  • AWS S3 ACL Permissions Documentation: https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html
  • OWASP Testing Guide – Cloud Storage: https://owasp.org/www-project-web-security-testing-guide/
  • Kali Linux Tool Listing: https://www.kali.org/tools/s3scanner/
Total
0
Shares

Leave a Reply

Previous Post
CloudBrute: Complete Guide to Cloud Asset Discovery and Attack Surface Enumeration Using Kali Linux

CloudBrute: Complete Guide to Cloud Asset Discovery and Attack Surface Enumeration Using Kali Linux

Next Post
Trivy: Complete Guide to Container, Kubernetes, and Vulnerability Scanning Using Kali Linux

Trivy: Complete Guide to Container, Kubernetes, and Vulnerability Scanning Using Kali Linux

Related Posts