
Ein S3-Konto-ID-Enumeration- und Bucket-Erkennungstool
Ein Tool zur Aufzählung von S3-Konto-IDs und zur Entdeckung von Buckets
Bei einem einzelnen zugänglichen S3-Bucket extrahiert bucky die 12-stellige AWS-Konto-ID des Besitzers und entdeckt dann weitere Buckets desselben Kontos, indem es Bucket-Namen gegen eine Wortliste fuzzt – alles in einem Befehl.
s3:ResourceAccount, um die 12-stellige AWS-Konto-ID mithilfe von Inline-STS-Sitzungsrichtlinien Ziffer für Ziffer durch Brute-Force zu ermitteln.S3-Bucket-Namen teilten ursprünglich einen einzigen globalen Namensraum, was zu Bucketsquatting führte – Angreifer konnten auf Namen sitzen bleiben, von denen sie erwarteten, dass Organisationen sie erstellen würden. AWS hat dies durch die Einführung kontoregionaler Namensräume behoben, einem Namensschema, das jeden Bucket an sein besitzendes Konto und seine Region bindet:
{name}-{accountID}-{region}-an
Ein Bucket namens myapp-123456789123-eu-north-1-an würde sich unter https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com befinden. AWS empfiehlt dieses Format jetzt für neue Buckets, auch wenn es noch nicht die Standardeinstellung ist. (Hintergrundinformationen dazu, wie der neue Namensraum Bucketsquatting beendet, finden Sie unter One Cloud Please.)
Der Nachteil ist, dass die Konto-ID und die Region nun in den Bucket-Namen selbst eingebettet sind. Sobald ein Angreifer die Konto-ID eines Ziels erlangt, kann er sie mit einer Wortliste kombinieren und systematisch gültige Bucket-URLs konstruieren – und S3 wird bestätigen, ob jeder einzelne existiert, selbst wenn der Bucket privat ist. Diese Antwort allein ist eine nützliche Aufklärung.
Bucky nutzt genau dies aus. Basierend auf Forschungsergebnissen von Pwned Labs stellt es zunächst die 12-stellige Konto-ID von jedem zugänglichen Bucket mithilfe der s3-account-search-Technik wieder her und brute-forct dann das Muster {name}-{accountID}-{region}-an, um die breitere S3-Fußabdruck des Ziels aufzudecken.
s3:ListBucket oder s3:GetObject auf dem Ziel-Bucket hat.sts:AssumeRole für diese Rolle auf und übergeben eine Inline-Sitzungsrichtlinie mit einer s3:ResourceAccount-Bedingung wie "1*".1 beginnt, ist der HeadBucket-Aufruf erfolgreich; andernfalls wird 403 zurückgegeben.Dies erfordert höchstens 120 API-Aufrufe (12 Positionen × 10 Ziffern) und ist normalerweise in unter einer Minute abgeschlossen.
go installgo install github.com/umair9747/bucky@latest
git clone https://github.com/umair9747/bucky.git
cd bucky
go build -o bucky .
sudo mv bucky /usr/local/bin/
bucky --update
Dies zieht die neueste Version aus dem Repository und installiert sie.
Bevor Sie bucky verwenden, benötigen Sie eine IAM-Rolle in Ihrem eigenen AWS-Konto, die auf den Ziel-S3-Bucket zugreifen kann. Der Ziel-Bucket muss öffentlich zugänglich sein oder eine Bucket-Richtlinie haben, die den Zugriff von Ihrem Konto aus erlaubt.
Erstellen Sie trust-policy.json – dies erlaubt Ihrem IAM-Benutzer, die Rolle zu übernehmen:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<YOUR_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Ersetzen Sie
<YOUR_ACCOUNT_ID>durch Ihre 12-stellige AWS-Konto-ID. Sie können den Prinzipal auf eine bestimmte IAM-Benutzer- oder Rollen-ARN anstelle von:rooteingrenzen.
Erstellen Sie s3-policy.json – die Rolle benötigt breiten S3-Lesezugriff (die s3:ResourceAccount-Bedingung in buckys Inline-Sitzungsrichtlinie übernimmt die Kontofilterung):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": "*"
}
]
}
aws iam create-role \
--role-name bucky-role \
--assume-role-policy-document file://trust-policy.json
aws iam put-role-policy \
--role-name bucky-role \
--policy-name S3ReadAccess \
--policy-document file://s3-policy.json
aws iam get-role --role-name bucky-role --query 'Role.Arn' --output text
# Ausgabe: arn:aws:iam::123456789012:role/bucky-role
Wenn Ihr IAM-Benutzer noch nicht über die sts:AssumeRole-Berechtigung verfügt, fügen Sie sie hinzu:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/bucky-role"
}
]
}
Die primäre Art, bucky zu verwenden – Konto-ID aus einem bekannten Bucket ermitteln und dann in einem Durchgang nach weiteren Buckets fuzzen:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket \
--wordlist wordlists/default.txt \
--access-key AKIA... \
--secret-key wJal...
Mit einem bekannten Objektschlüssel (verbessert die Zuverlässigkeit):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket s3://target-bucket/index.html \
--wordlist wordlists/default.txt \
--workers 20
Mehrere Buckets (kommasepariert):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket bucket1,bucket2,bucket3 \
--wordlist wordlists/default.txt
Mehrere Buckets aus einer Datei:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket-file targets.txt \
--wordlist wordlists/default.txt
Ergebnisse als JSON speichern:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Ausgabe:
=== Phase 1: Konten-ID-Ermittlung ===
[*] Überprüfe Zugriff auf Bucket: target-bucket
[+] Zugriff bestätigt
[+] Bucket-Region: us-west-2
[*] Ermittle Konto-ID...
[██████████████████████████████] 12/12 | 675351422352
[+] Konto-ID: 675351422352
=== Phase 2: Bucket-Entdeckung ===
[*] Fuzze Buckets für Konto: 675351422352
[*] 312 Kandidaten aus Wortliste geladen
[+] GEFUNDEN: target-backups
[+] GEFUNDEN: target-logs
[██████████████████████████████] 312/312 | 2 gefunden
=== Zusammenfassung ===
Konto-ID : 675351422352
Quelle : target-bucket
Region : us-west-2
Entdeckt : 2 weitere Buckets
- target-backups
- target-logs
Wenn Sie nur die Konto-ID benötigen:
bucky enum \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket
Mehrere Buckets und JSON-Ausgabe funktionieren auch mit Unterbefehlen:
bucky enum --bucket bucket1,bucket2 --json
bucky enum --bucket-file targets.txt --json --output results.json
Wenn Sie bereits eine Konto-ID haben und Buckets entdecken möchten:
bucky fuzz \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--account-id 675351422352 \
--wordlist wordlists/default.txt \
--workers 20
Alle Flags können über Umgebungsvariablen gesetzt werden. Flags haben Vorrang, wenn beide gesetzt sind.
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=wJal...
export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role
# Jetzt einfach das Ziel angeben
bucky --bucket target-bucket --wordlist wordlists/default.txt
Bucky wird mit einer Standardwortliste unter wordlists/default.txt ausgeliefert, die etwa 300 gängige S3-Bucket-Namensmuster enthält:
backups, logs, data, assets, uploads)cloudtrail-logs, terraform-state, lambda-artifacts)prod-logs, staging-data, dev-backups)api, web-assets, cdn-origin)ci-artifacts, , )Für gezielte Engagements generieren Sie eine benutzerdefinierte Wortliste, indem Sie den Organisationsnamen voranstellen:
ORG="acme"
while read -r line; do
[[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
echo "${ORG}-${line}"
echo "${line}-${ORG}"
echo "${ORG}${line}"
done < wordlists/default.txt > wordlists/acme.txt
Jede Wortliste, die mit Tools wie ffuf oder gobuster kompatibel ist, funktioniert. Format: ein Bucket-Name pro Zeile, # Kommentare, leere Zeilen werden ignoriert.
| Befehl | Beschreibung |
|---|---|
bucky | Vollständiger Workflow – Konto-ID ermitteln, dann nach weiteren Buckets fuzzen |
bucky enum | Ermittelt die 12-stellige Konto-ID aus einem bekannten Bucket |
bucky fuzz | Fuzzt Bucket-Namen gegen eine bekannte Konto-ID |
Globale Flags (alle Befehle):
bucky (vollständiger Workflow):
| Flag | Beschreibung |
|---|---|
bucky enum:
| Flag | Beschreibung |
|---|---|
--bucket | Ziel-S3-Bucket(s), kommasepariert |
--bucket-file | Datei mit Bucket-Namen/URLs, eine pro Zeile |
bucky fuzz:
| Flag | Beschreibung |
|---|---|
Das Flag --bucket und --bucket-file akzeptieren mehrere Eingabeformate. Bucky extrahiert automatisch den Bucket-Namen (und optionalen Schlüssel) aus:
| Format | Beispiel |
|---|---|
| Einfacher Name | my-bucket |
| S3-URI | s3://my-bucket/path/to/key |
Mehrere Buckets können kommasepariert über --bucket übergeben werden:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
Oder zeilenweise in einer Datei über --bucket-file aufgelistet:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
Wenn mehrere Buckets zur gleichen Konto-ID aufgelöst werden, dedupliziert bucky und führt das Fuzzing nur einmal pro eindeutigem Konto durch.
Verwenden Sie --json, um Ergebnisse in einer JSON-Datei zu speichern. Der Standarddateiname ist bucky-{uuid}.json im aktuellen Verzeichnis, oder geben Sie einen Pfad mit --output an:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Ausgabeformat:
{
"timestamp": "2024-01-15T10:30:00Z",
"results": [
{
"bucket": "target-bucket",
"account_id": "675351422352",
"region": "ap-south-1",
"discovered_buckets": [
"dev-675351422352-ap-south-1-an.s3.ap-south-1.amazonaws.com",
"prod-675351422352-ap-south-1-an.s3.ap-south-1.amazonaws.com"
]
}
]
}
Bucky erkennt automatisch die Region von Ziel-Buckets. Wenn S3 eine 301-Weiterleitung zurückgibt (Bucket befindet sich in einer anderen Region als --region), ermittelt bucky die korrekte Region über den HTTP-Antwortheader x-amz-bucket-region und speichert sie für alle nachfolgenden Anfragen zwischen. Für den Ziel-Bucket ist keine manuelle Region-Konfiguration erforderlich.
Wenn Sie Fragen oder Feedback zu Genzai haben oder einfach nur mit mir in Kontakt treten möchten, können Sie mich gerne über LinkedIn oder E-Mail erreichen.
| Variable | Flag | Beschreibung |
|---|
AWS_ACCESS_KEY_ID | --access-key | AWS-Zugriffsschlüssel-ID |
AWS_SECRET_ACCESS_KEY | --secret-key | AWS-Geheimzugriffsschlüssel |
AWS_SESSION_TOKEN | --session-token | AWS-Sitzungstoken (für temporäre Anmeldedaten) |
AWS_REGION | --region | AWS-Region (Standard: us-east-1) |
AWS_DEFAULT_REGION | --region | Fallback, wenn AWS_REGION nicht gesetzt ist |
AWS_PROFILE | --profile | AWS-benanntes Profil aus ~/.aws/credentials |
BUCKY_ROLE_ARN | --role-arn | ARN der zu übernehmenden IAM-Rolle |
BUCKY_BUCKET | --bucket | Name des Ziel-S3-Buckets |
BUCKY_ACCOUNT_ID | --account-id | Ziel-AWS-Konto-ID (nur fuzz) |
BUCKY_WORDLIST | --wordlist | Pfad zur Wortlistendatei |
BUCKY_WORKERS | --workers | Gleichzeitige Fuzzing-Arbeiter (Standard: 10) |
build-outputdocker-images| Flag | Beschreibung |
|---|
--access-key | AWS-Zugriffsschlüssel-ID |
--secret-key | AWS-Geheimzugriffsschlüssel |
--session-token | AWS-Sitzungstoken |
--region | AWS-Region (Standard: us-east-1) |
--profile | AWS-benanntes Profil |
--role-arn | ARN der zu übernehmenden IAM-Rolle |
--json | Ergebnisse als JSON-Datei speichern |
--output | JSON-Ausgabedateipfad (Standard: bucky-{uuid}.json) |
--bucket| Ziel-S3-Bucket(s), kommasepariert |
--bucket-file | Datei mit Bucket-Namen/URLs, eine pro Zeile |
--wordlist | Pfad zur Wortlistendatei |
--workers | Gleichzeitige Arbeiter (Standard: 10) |
--account-id| Ziel-12-stellige AWS-Konto-ID |
--wordlist | Pfad zur Wortlistendatei |
--workers | Gleichzeitige Arbeiter (Standard: 10) |
--regions | Kommaseparierte Regionen für Namensmutationen |
| Virtual-Hosted-URL |
https://my-bucket.s3.us-west-2.amazonaws.com/key |
| Path-Style-URL | https://s3.us-west-2.amazonaws.com/my-bucket/key |