
Una herramienta de enumeración de ID de cuenta S3 y descubrimiento de cubos
Una herramienta de enumeración de ID de cuenta S3 y descubrimiento de buckets
Dado un único bucket S3 accesible, bucky extrae el ID de cuenta AWS de 12 dígitos que lo posee, luego descubre buckets adicionales pertenecientes a la misma cuenta probando nombres de buckets contra una lista de palabras — todo en un solo comando.
s3:ResourceAccount para forzar bruto el ID de cuenta AWS de 12 dígitos un dígito a la vez mediante políticas de sesión STS en líneaOriginalmente, los nombres de los buckets S3 compartían un único espacio de nombres global, lo que dio lugar al bucketsquatting — los atacantes podían apropiarse de nombres que esperaban que las organizaciones crearan. AWS abordó esto implementando espacios de nombres regionales por cuenta, un esquema de nombres que vincula cada bucket a su cuenta y región propietarias:
{nombre}-{IDcuenta}-{región}-an
Un bucket llamado myapp-123456789123-eu-north-1-an residiría en https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com. AWS ahora recomienda este formato para buckets nuevos, aunque aún no es el predeterminado. (Para conocer los antecedentes de cómo el nuevo espacio de nombres elimina el bucketsquatting, consulte One Cloud Please.)
La contrapartida es que el ID de cuenta y la región ahora están incorporados en el nombre del bucket. Una vez que un atacante obtiene el ID de cuenta de un objetivo, puede combinarlo con una lista de palabras y construir sistemáticamente URLs de buckets válidas — y S3 confirmará si cada una existe, incluso si el bucket es privado. Esa respuesta por sí sola es una valiosa inteligencia.
Bucky explota precisamente esto. Basándose en la investigación de Pwned Labs, primero recupera el ID de cuenta de 12 dígitos de cualquier bucket accesible utilizando la técnica s3-account-search, luego fuerza bruta el patrón {nombre}-{IDcuenta}-{región}-an para descubrir la huella S3 más amplia del objetivo.
s3:ListBucket o s3:GetObject en el bucket objetivosts:AssumeRole en ese rol, pasando una política de sesión en línea con una condición s3:ResourceAccount como "1*"1, la llamada HeadBucket tiene éxito; de lo contrario, devuelve 403Esto requiere como máximo 120 llamadas API (12 posiciones × 10 dígitos) y suele completarse en menos de 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
Esto descarga e instala la última versión del repositorio.
Antes de usar bucky, necesitas un rol IAM en tu propia cuenta AWS que pueda acceder al bucket S3 objetivo. El bucket objetivo debe ser accesible públicamente o tener una política de bucket que permita el acceso desde tu cuenta.
Crea trust-policy.json — esto permite que tu usuario IAM asuma el rol:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<TU_ID_DE_CUENTA>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Reemplaza
<TU_ID_DE_CUENTA>con tu ID de cuenta AWS de 12 dígitos. Puedes limitar el principal a un usuario IAM específico o ARN de rol en lugar de:root.
Crea s3-policy.json — el rol necesita permisos de lectura amplios en S3 (la condición s3:ResourceAccount en la política de sesión en línea de bucky maneja el filtrado a nivel de cuenta):
{
"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
# Salida: arn:aws:iam::123456789012:role/bucky-role
Si tu usuario IAM aún no tiene permiso sts:AssumeRole, adjúntalo:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<TU_ID_DE_CUENTA>:role/bucky-role"
}
]
}
La forma principal de usar bucky — enumerar el ID de cuenta desde un bucket conocido, luego probar más buckets en un solo paso:
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 clave de objeto conocida (mejora la fiabilidad):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket s3://target-bucket/index.html \
--wordlist wordlists/default.txt \
--workers 20
Múltiples buckets (separados por comas):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket bucket1,bucket2,bucket3 \
--wordlist wordlists/default.txt
Múltiples buckets desde un archivo:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket-file targets.txt \
--wordlist wordlists/default.txt
Guardar resultados en JSON:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Salida:
=== Fase 1: Enumeración de ID de cuenta ===
[*] Verificando acceso al bucket: target-bucket
[+] Acceso confirmado
[+] Región del bucket: us-west-2
[*] Enumerando ID de cuenta...
[██████████████████████████████] 12/12 | 675351422352
[+] ID de cuenta: 675351422352
=== Fase 2: Descubrimiento de buckets ===
[*] Probando buckets para la cuenta: 675351422352
[*] Cargadas 312 candidatos de la lista de palabras
[+] ENCONTRADO: target-backups
[+] ENCONTRADO: target-logs
[██████████████████████████████] 312/312 | 2 encontrados
=== Resumen ===
ID de cuenta : 675351422352
Fuente : target-bucket
Región : us-west-2
Descubiertos: 2 bucket(s) adicional(es)
- target-backups
- target-logs
Si solo necesitas el ID de cuenta:
bucky enum \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket
Múltiples buckets y salida JSON también funcionan con subcomandos:
bucky enum --bucket bucket1,bucket2 --json
bucky enum --bucket-file targets.txt --json --output results.json
Si ya tienes un ID de cuenta y deseas descubrir buckets:
bucky fuzz \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--account-id 675351422352 \
--wordlist wordlists/default.txt \
--workers 20
Todos los flags pueden configurarse mediante variables de entorno. Los flags tienen prioridad cuando ambos están establecidos.
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=wJal...
export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role
# Ahora solo especifica el objetivo
bucky --bucket target-bucket --wordlist wordlists/default.txt
Bucky incluye una lista de palabras predeterminada en wordlists/default.txt con aproximadamente 300 patrones de nombres de buckets S3 comunes:
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 compromisos dirigidos, genera una lista de palabras personalizada anteponiendo el nombre de la organización:
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
Cualquier lista de palabras compatible con herramientas como ffuf o gobuster funciona. Formato: un nombre de bucket por línea, comentarios con #, líneas en blanco ignoradas.
| Comando | Descripción |
|---|---|
bucky | Flujo de trabajo completo — enumera ID de cuenta y luego prueba más buckets |
bucky enum | Enumera el ID de cuenta de 12 dígitos desde un bucket conocido |
bucky fuzz | Prueba nombres de buckets contra un ID de cuenta conocido |
Flags globales (todos los comandos):
bucky (flujo de trabajo completo):
| Flag | Descripción |
|---|---|
bucky enum:
| Flag | Descripción |
|---|---|
--bucket | Bucket(s) S3 objetivo, separados por comas |
--bucket-file | Archivo con nombres/URLs de buckets, uno por línea |
bucky fuzz:
| Flag | Descripción |
|---|
El flag --bucket y --bucket-file aceptan múltiples formatos de entrada. Bucky extrae automáticamente el nombre del bucket (y la clave opcional) de:
| Formato | Ejemplo |
|---|---|
| Nombre simple | my-bucket |
| URI S3 | s3://my-bucket/path/to/key |
Se pueden pasar múltiples buckets separados por comas mediante --bucket:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
O listados uno por línea en un archivo mediante --bucket-file:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
Cuando múltiples buckets resuelven al mismo ID de cuenta, bucky elimina duplicados y ejecuta el fuzzing solo una vez por cuenta única.
Usa --json para guardar los resultados en un archivo JSON. El nombre de archivo predeterminado es bucky-{uuid}.json en el directorio actual, o especifica una ruta con --output:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Formato de salida:
{
"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 detecta automáticamente la región de los buckets objetivo. Cuando S3 devuelve una redirección 301 (el bucket está en una región diferente a --region), bucky resuelve la región correcta mediante el encabezado de respuesta HTTP x-amz-bucket-region y lo almacena en caché para todas las solicitudes posteriores. No se necesita configuración manual de región para el bucket objetivo.
Si tienes alguna pregunta o comentario sobre Genzai o simplemente quieres contactarte conmigo, no dudes en escribirme a través de LinkedIn o Correo electrónico.
| Variable | Flag | Descripción |
|---|
AWS_ACCESS_KEY_ID | --access-key | ID de clave de acceso AWS |
AWS_SECRET_ACCESS_KEY | --secret-key | Clave de acceso secreta AWS |
AWS_SESSION_TOKEN | --session-token | Token de sesión AWS (para credenciales temporales) |
AWS_REGION | --region | Región AWS (predeterminada: us-east-1) |
AWS_DEFAULT_REGION | --region | Alternativa si AWS_REGION no está configurada |
AWS_PROFILE | --profile | Perfil AWS desde ~/.aws/credentials |
BUCKY_ROLE_ARN | --role-arn | ARN del rol IAM a asumir |
BUCKY_BUCKET | --bucket | Nombre del bucket S3 objetivo |
BUCKY_ACCOUNT_ID | --account-id | ID de cuenta AWS objetivo (solo fuzz) |
BUCKY_WORDLIST | --wordlist | Ruta al archivo de lista de palabras |
BUCKY_WORKERS | --workers | Workers concurrentes de fuzzing (predeterminado: 10) |
build-outputdocker-images| Flag | Descripción |
|---|
--access-key | ID de clave de acceso AWS |
--secret-key | Clave de acceso secreta AWS |
--session-token | Token de sesión AWS |
--region | Región AWS (predeterminada: us-east-1) |
--profile | Perfil AWS |
--role-arn | ARN del rol IAM a asumir |
--json | Guarda resultados en archivo JSON |
--output | Ruta del archivo de salida JSON (predeterminado: bucky-{uuid}.json) |
--bucket |
| Bucket(s) S3 objetivo, separados por comas |
--bucket-file | Archivo con nombres/URLs de buckets, uno por línea |
--wordlist | Ruta al archivo de lista de palabras |
--workers | Workers concurrentes (predeterminado: 10) |
--account-id | ID de cuenta AWS de 12 dígitos objetivo |
--wordlist | Ruta al archivo de lista de palabras |
--workers | Workers concurrentes (predeterminado: 10) |
--regions | Regiones separadas por comas para mutaciones de nombres |
| 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 |