
Uma ferramenta de enumeração de IDs de contas e descoberta de buckets do S3
Uma ferramenta de enumeração de ID de conta S3 e descoberta de buckets
Dado um único bucket S3 acessível, o bucky extrai o ID da conta AWS de 12 dígitos que o possui, então descobre buckets adicionais pertencentes à mesma conta por meio de fuzzing de nomes de buckets contra uma wordlist — tudo em um único comando.
s3:ResourceAccount para forçar bruto o ID da conta AWS de 12 dígitos um dígito de cada vez por meio de políticas de sessão STS inlineOs nomes de buckets S3 originalmente compartilhavam um único namespace global, o que deu origem ao bucketsquatting — atacantes podiam ocupar nomes que esperavam que organizações criassem. A AWS resolveu isso implementando namespaces conta-regionais, um esquema de nomenclatura que vincula cada bucket à sua conta e região proprietárias:
{name}-{accountID}-{region}-an
Um bucket chamado myapp-123456789123-eu-north-1-an estaria em https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com. A AWS agora recomenda este formato para novos buckets, embora ainda não seja o padrão. (Para contexto sobre como o novo namespace elimina o bucketsquatting, veja One Cloud Please.)
A desvantagem é que o ID da conta e a região agora estão embutidos no próprio nome do bucket. Uma vez que um atacante obtém o ID da conta de um alvo, ele pode combiná-lo com uma wordlist e construir sistematicamente URLs de bucket válidos — e o S3 confirmará se cada um existe, mesmo que o bucket seja privado. Essa resposta por si só já é um reconhecimento útil.
Bucky explora exatamente isso. Com base em pesquisa do Pwned Labs, ele primeiro recupera o ID da conta de 12 dígitos de qualquer bucket acessível usando a técnica s3-account-search, depois força bruta o padrão {name}-{accountID}-{region}-an para descobrir a pegada S3 mais ampla do alvo.
s3:ListBucket ou s3:GetObject no bucket alvosts:AssumeRole nessa função, passando uma política de sessão inline com uma condição s3:ResourceAccount como "1*"1, a chamada HeadBucket é bem-sucedida; caso contrário, retorna 403Isso requer no máximo 120 chamadas de API (12 posições × 10 dígitos) e normalmente é concluído em menos de um 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
Isso baixa e instala a versão mais recente do repositório.
Antes de usar o bucky, você precisa de uma função IAM em sua própria conta AWS que possa acessar o bucket S3 alvo. O bucket alvo deve ser publicamente acessível ou ter uma política de bucket que permita o acesso a partir de sua conta.
Crie trust-policy.json — isso permite que seu usuário IAM assuma a função:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<YOUR_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Substitua
<YOUR_ACCOUNT_ID>pelo seu ID de conta AWS de 12 dígitos. Você pode restringir o principal a um usuário IAM específico ou ARN de função em vez de:root.
Crie s3-policy.json — a função precisa de acesso de leitura S3 amplo (a condição s3:ResourceAccount na política de sessão inline do bucky lida com a filtragem no nível da conta):
{
"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 seu usuário IAM ainda não tiver permissão sts:AssumeRole, anexe-a:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/bucky-role"
}
]
}
A maneira principal de usar o bucky — enumerar o ID da conta a partir de um bucket conhecido, depois fazer fuzzing para mais buckets em um único comando:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket \
--wordlist wordlists/default.txt \
--access-key AKIA... \
--secret-key wJal...
Com uma chave de objeto conhecida (melhora a confiabilidade):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket s3://target-bucket/index.html \
--wordlist wordlists/default.txt \
--workers 20
Múltiplos buckets (separados por vírgula):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket bucket1,bucket2,bucket3 \
--wordlist wordlists/default.txt
Múltiplos buckets a partir de um arquivo:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket-file targets.txt \
--wordlist wordlists/default.txt
Salvar resultados em JSON:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Output:
=== Phase 1: Account ID Enumeration ===
[*] Verifying access to bucket: target-bucket
[+] Access confirmed
[+] Bucket region: us-west-2
[*] Enumerating account ID...
[██████████████████████████████] 12/12 | 675351422352
[+] Account ID: 675351422352
=== Phase 2: Bucket Discovery ===
[*] Fuzzing buckets for account: 675351422352
[*] Loaded 312 candidates from wordlist
[+] FOUND: target-backups
[+] FOUND: target-logs
[██████████████████████████████] 312/312 | 2 found
=== Summary ===
Account ID : 675351422352
Source : target-bucket
Region : us-west-2
Discovered : 2 additional bucket(s)
- target-backups
- target-logs
Se você precisa apenas do ID da conta:
bucky enum \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket
Múltiplos buckets e saída JSON também funcionam com subcomandos:
bucky enum --bucket bucket1,bucket2 --json
bucky enum --bucket-file targets.txt --json --output results.json
Se você já tem um ID de conta e quer descobrir buckets:
bucky fuzz \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--account-id 675351422352 \
--wordlist wordlists/default.txt \
--workers 20
Todas as flags podem ser definidas via variáveis de ambiente. As flags têm precedência quando ambas estão definidas.
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=wJal...
export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role
# Now just specify the target
bucky --bucket target-bucket --wordlist wordlists/default.txt
O Bucky vem com uma wordlist padrão em wordlists/default.txt contendo ~300 padrões comuns de nomenclatura de buckets 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, , )Para engajamentos direcionados, gere uma wordlist personalizada adicionando o nome da organização no início:
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
Qualquer wordlist compatível com ferramentas como ffuf ou gobuster funciona. Formato: um nome de bucket por linha, comentários com #, linhas em branco ignoradas.
| Command | Description |
|---|---|
bucky | Fluxo de trabalho completo — enumera o ID da conta e depois faz fuzzing para mais buckets |
bucky enum | Enumera o ID da conta de 12 dígitos a partir de um bucket conhecido |
bucky fuzz | Faz fuzzing de nomes de buckets contra um ID de conta conhecido |
Flags globais (todos os comandos):
bucky (fluxo de trabalho completo):
| Flag | Description |
|---|---|
bucky enum:
| Flag | Description |
|---|---|
--bucket | Bucket(s) S3 alvo, separados por vírgula |
--bucket-file | Arquivo com nomes/URLs de buckets, um por linha |
bucky fuzz:
| Flag | Description |
|---|---|
A flag --bucket e o --bucket-file aceitam múltiplos formatos de entrada. O Bucky extrai automaticamente o nome do bucket (e chave opcional) de:
| Format | Example |
|---|---|
| Nome simples | my-bucket |
| URI S3 | s3://my-bucket/path/to/key |
Múltiplos buckets podem ser passados separados por vírgula via --bucket:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
Ou listados um por linha em um arquivo via --bucket-file:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
Quando múltiplos buckets resolvem para o mesmo ID de conta, o bucky deduplica e executa o fuzzing apenas uma vez por conta única.
Use --json para salvar os resultados em um arquivo JSON. O nome padrão do arquivo é bucky-{uuid}.json no diretório atual, ou especifique um caminho com --output:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Formato de saída:
{
"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"
]
}
]
}
O Bucky detecta automaticamente a região dos buckets alvo. Quando o S3 retorna um redirecionamento 301 (o bucket está em uma região diferente da --region), o bucky resolve a região correta através do cabeçalho de resposta HTTP x-amz-bucket-region e a armazena em cache para todas as solicitações subsequentes. Nenhuma configuração manual de região é necessária para o bucket alvo.
Se você tiver alguma dúvida ou feedback sobre o Genzai ou apenas quiser se conectar comigo, sinta-se à vontade para entrar em contato via LinkedIn ou Email.
| Variable | Flag | Description |
|---|
AWS_ACCESS_KEY_ID | --access-key | ID da chave de acesso AWS |
AWS_SECRET_ACCESS_KEY | --secret-key | Chave de acesso secreta AWS |
AWS_SESSION_TOKEN | --session-token | Token de sessão AWS (para credenciais temporárias) |
AWS_REGION | --region | Região AWS (padrão: us-east-1) |
AWS_DEFAULT_REGION | --region | Fallback se AWS_REGION não estiver definida |
AWS_PROFILE | --profile | Perfil nomeado AWS de ~/.aws/credentials |
BUCKY_ROLE_ARN | --role-arn | ARN da função IAM a ser assumida |
BUCKY_BUCKET | --bucket | Nome do bucket S3 alvo |
BUCKY_ACCOUNT_ID | --account-id | ID da conta AWS alvo (apenas fuzz) |
BUCKY_WORDLIST | --wordlist | Caminho para o arquivo de wordlist |
BUCKY_WORKERS | --workers | Workers de fuzzing concorrentes (padrão: 10) |
build-outputdocker-images| Flag | Description |
|---|
--access-key | ID da chave de acesso AWS |
--secret-key | Chave de acesso secreta AWS |
--session-token | Token de sessão AWS |
--region | Região AWS (padrão: us-east-1) |
--profile | Perfil nomeado AWS |
--role-arn | ARN da função IAM a ser assumida |
--json | Salvar resultados em arquivo JSON |
--output | Caminho do arquivo de saída JSON (padrão: bucky-{uuid}.json) |
--bucket |
| Bucket(s) S3 alvo, separados por vírgula |
--bucket-file | Arquivo com nomes/URLs de buckets, um por linha |
--wordlist | Caminho para o arquivo de wordlist |
--workers | Workers concorrentes (padrão: 10) |
--account-id |
| ID da conta AWS alvo de 12 dígitos |
--wordlist | Caminho para o arquivo de wordlist |
--workers | Workers concorrentes (padrão: 10) |
--regions | Regiões separadas por vírgula para mutações de nome |
| URL de host virtual |
https://my-bucket.s3.us-west-2.amazonaws.com/key |
| URL estilo caminho | https://s3.us-west-2.amazonaws.com/my-bucket/key |