
Uno strumento di enumerazione degli ID account S3 e di scoperta dei bucket
Uno strumento per l'enumerazione degli ID account S3 e la scoperta di bucket
Dato un singolo bucket S3 accessibile, bucky estrae l'ID account AWS di 12 cifre che lo possiede, poi scopre bucket aggiuntivi appartenenti allo stesso account fuzzando i nomi dei bucket contro una wordlist — tutto in un unico comando.
s3:ResourceAccount per forzare l'ID account AWS di 12 cifre una cifra alla volta attraverso policy di sessione STS inlineI nomi dei bucket S3 originariamente condividevano un unico namespace globale, il che ha dato origine al bucketsquatting — gli attaccanti potevano accaparrarsi nomi che si aspettavano che le organizzazioni creassero. AWS ha risolto questo problema implementando namespace account-regionali, uno schema di denominazione che lega ogni bucket al suo account e regione proprietari:
{nome}-{accountID}-{regione}-an
Un bucket chiamato myapp-123456789123-eu-north-1-an si troverebbe all'indirizzo https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com. AWS ora raccomanda questo formato per i nuovi bucket, anche se non è ancora il default. (Per approfondimenti su come il nuovo namespace elimina il bucketsquatting, vedi One Cloud Please.)
Il compromesso è che l'ID account e la regione sono ora incorporati nel nome del bucket stesso. Una volta che un attaccante ottiene l'ID account di un target, può abbinarlo a una wordlist e costruire sistematicamente URL di bucket validi — e S3 confermerà se ciascuno esiste, anche se il bucket è privato. Quella risposta da sola è una ricognizione utile.
Bucky sfrutta proprio questo. Basandosi sulla ricerca di Pwned Labs, recupera prima l'ID account di 12 cifre da qualsiasi bucket accessibile utilizzando la tecnica s3-account-search, poi forza bruta il pattern {nome}-{accountID}-{regione}-an per scoprire la più ampia impronta S3 del target.
s3:ListBucket o s3:GetObject sul bucket targetsts:AssumeRole su quel ruolo, passando una policy di sessione inline con una condizione s3:ResourceAccount come "1*"1, la chiamata HeadBucket ha successo; altrimenti restituisce 403Questo richiede al massimo 120 chiamate API (12 posizioni × 10 cifre) e tipicamente si completa in meno di un minuto.
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
Questo recupera e installa l'ultima versione dal repository.
Prima di usare bucky, hai bisogno di un ruolo IAM nel tuo account AWS che possa accedere al bucket S3 target. Il bucket target deve essere pubblicamente accessibile o avere una policy del bucket che consenta l'accesso dal tuo account.
Crea trust-policy.json — questo permette al tuo utente IAM di assumere il ruolo:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<TUO_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Sostituisci
<TUO_ACCOUNT_ID>con il tuo ID account AWS di 12 cifre. Puoi restringere il principal a uno specifico ARN di utente o ruolo IAM invece di:root.
Crea s3-policy.json — il ruolo necessita di accesso in lettura S3 ampio (la condizione s3:ResourceAccount nella policy di sessione inline di bucky gestisce il filtraggio a livello di account):
{
"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
# Output: arn:aws:iam::123456789012:role/bucky-role
Se il tuo utente IAM non ha già l'autorizzazione sts:AssumeRole, allegala:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<TUO_ACCOUNT_ID>:role/bucky-role"
}
]
}
Il modo principale di usare bucky — enumera l'ID account da un bucket noto, poi fuzza per più bucket in un colpo solo:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket \
--wordlist wordlists/default.txt \
--access-key AKIA... \
--secret-key wJal...
Con una chiave oggetto nota (migliora l'affidabilità):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket s3://target-bucket/index.html \
--wordlist wordlists/default.txt \
--workers 20
Più bucket (separati da virgola):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket bucket1,bucket2,bucket3 \
--wordlist wordlists/default.txt
Più bucket da un file:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket-file targets.txt \
--wordlist wordlists/default.txt
Salva i risultati in JSON:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Output:
=== Fase 1: Enumerazione ID Account ===
[*] Verifica accesso al bucket: target-bucket
[+] Accesso confermato
[+] Regione bucket: us-west-2
[*] Enumerazione ID account...
[██████████████████████████████] 12/12 | 675351422352
[+] ID Account: 675351422352
=== Fase 2: Scoperta Bucket ===
[*] Fuzzing bucket per account: 675351422352
[*] Caricati 312 candidati dalla wordlist
[+] TROVATO: target-backups
[+] TROVATO: target-logs
[██████████████████████████████] 312/312 | 2 trovati
=== Riepilogo ===
ID Account : 675351422352
Sorgente : target-bucket
Regione : us-west-2
Scoperti : 2 bucket aggiuntivi
- target-backups
- target-logs
Se hai solo bisogno dell'ID account:
bucky enum \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket
Più bucket e output JSON funzionano anche con i sottocomandi:
bucky enum --bucket bucket1,bucket2 --json
bucky enum --bucket-file targets.txt --json --output results.json
Se hai già un ID account e vuoi scoprire bucket:
bucky fuzz \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--account-id 675351422352 \
--wordlist wordlists/default.txt \
--workers 20
Tutti i flag possono essere impostati tramite variabili d'ambiente. I flag hanno la precedenza quando entrambi sono impostati.
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=wJal...
export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role
# Ora specifica solo il target
bucky --bucket target-bucket --wordlist wordlists/default.txt
Bucky è fornito con una wordlist predefinita in wordlists/default.txt contenente circa 300 pattern comuni di denominazione di bucket S3:
backups, logs, data, assets, uploads)cloudtrail-logs, terraform-state, lambda-artifacts)prod-logs, staging-data, dev-backups)api, web-assets, cdn-origin)ci-artifacts, , )Per engagement mirati, genera una wordlist personalizzata aggiungendo il nome dell'organizzazione:
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
Qualsiasi wordlist compatibile con strumenti come ffuf o gobuster funziona. Formato: un nome bucket per riga, commenti #, righe vuote ignorate.
| Comando | Descrizione |
|---|---|
bucky | Flusso di lavoro completo — enumera ID account poi fuzza per più bucket |
bucky enum | Enumera l'ID account di 12 cifre da un bucket noto |
bucky fuzz | Fuzza i nomi dei bucket contro un ID account noto |
Flag globali (tutti i comandi):
bucky (flusso di lavoro completo):
| Flag | Descrizione |
|---|---|
bucky enum:
| Flag | Descrizione |
|---|---|
--bucket | Bucket S3 target, separati da virgola |
--bucket-file | File con nomi/URL dei bucket, uno per riga |
bucky fuzz:
| Flag | Descrizione |
|---|---|
Il flag --bucket e --bucket-file accettano più formati di input. Bucky estrae automaticamente il nome del bucket (e la chiave opzionale) da:
| Formato | Esempio |
|---|---|
| Nome semplice | my-bucket |
| URI S3 | s3://my-bucket/path/to/key |
Più bucket possono essere passati separati da virgola tramite --bucket:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
Oppure elencati uno per riga in un file tramite --bucket-file:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
Quando più bucket risolvono allo stesso ID account, bucky deduplica ed esegue il fuzzing solo una volta per account univoco.
Usa --json per salvare i risultati in un file JSON. Il nome file predefinito è bucky-{uuid}.json nella directory corrente, oppure specifica un percorso con --output:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Formato di output:
{
"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 rileva automaticamente la regione dei bucket target. Quando S3 restituisce un reindirizzamento 301 (il bucket si trova in una regione diversa da --region), bucky risolve la regione corretta tramite l'intestazione della risposta HTTP x-amz-bucket-region e la memorizza nella cache per tutte le richieste successive. Non è necessaria alcuna configurazione manuale della regione per il bucket target.
Se hai domande o feedback su Genzai o semplicemente vuoi entrare in contatto con me, non esitare a contattarmi tramite LinkedIn o Email.
| Variabile | Flag | Descrizione |
|---|
AWS_ACCESS_KEY_ID | --access-key | ID chiave di accesso AWS |
AWS_SECRET_ACCESS_KEY | --secret-key | Chiave segreta di accesso AWS |
AWS_SESSION_TOKEN | --session-token | Token di sessione AWS (per credenziali temporanee) |
AWS_REGION | --region | Regione AWS (default: us-east-1) |
AWS_DEFAULT_REGION | --region | Fallback se AWS_REGION non è impostata |
AWS_PROFILE | --profile | Profilo AWS nominativo da ~/.aws/credentials |
BUCKY_ROLE_ARN | --role-arn | ARN del ruolo IAM da assumere |
BUCKY_BUCKET | --bucket | Nome bucket S3 target |
BUCKY_ACCOUNT_ID | --account-id | ID account AWS target (solo fuzz) |
BUCKY_WORDLIST | --wordlist | Percorso del file wordlist |
BUCKY_WORKERS | --workers | Worker concorrenti per fuzzing (default: 10) |
build-outputdocker-images| Flag | Descrizione |
|---|
--access-key | ID chiave di accesso AWS |
--secret-key | Chiave segreta di accesso AWS |
--session-token | Token di sessione AWS |
--region | Regione AWS (default: us-east-1) |
--profile | Profilo AWS nominativo |
--role-arn | ARN del ruolo IAM da assumere |
--json | Salva i risultati in file JSON |
--output | Percorso file di output JSON (default: bucky-{uuid}.json) |
--bucket| Bucket S3 target, separati da virgola |
--bucket-file | File con nomi/URL dei bucket, uno per riga |
--wordlist | Percorso del file wordlist |
--workers | Worker concorrenti (default: 10) |
--account-id| ID account AWS target di 12 cifre |
--wordlist | Percorso del file wordlist |
--workers | Worker concorrenti (default: 10) |
--regions | Regioni separate da virgola per mutazioni dei nomi |
| URL virtual-hosted |
https://my-bucket.s3.us-west-2.amazonaws.com/key |
| URL path-style | https://s3.us-west-2.amazonaws.com/my-bucket/key |