
Инструмент для перебора идентификаторов учетных записей S3 и обнаружения корзин
Инструмент для перечисления идентификаторов аккаунтов S3 и обнаружения бакетов
Имея один доступный бакет S3, Bucky извлекает 12-значный идентификатор аккаунта AWS, которому он принадлежит, а затем обнаруживает дополнительные бакеты того же аккаунта путем фаззинга имен бакетов по словарю — всё одной командой.
s3:ResourceAccount IAM для подбора 12-значного идентификатора аккаунта AWS по одной цифре за раз через встроенные политики сессий STSИмена бакетов S3 изначально использовали единое глобальное пространство имен, что породило bucketsquatting (захват имен бакетов) — злоумышленники могли "сидеть" на именах, которые организации планировали создать. AWS решила эту проблему, внедрив аккаунтно-региональное пространство имен — схему именования, привязывающую каждый бакет к его владельцу-аккаунту и региону:
{имя}-{accountID}-{region}-an
Бакет с именем myapp-123456789123-eu-north-1-an будет доступен по адресу https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com. AWS теперь рекомендует этот формат для новых бакетов, хотя он пока не является стандартным. (Подробнее о том, как новое пространство имен устраняет bucketsquatting, читайте в статье One Cloud Please.)
Обратная сторона в том, что идентификатор аккаунта и регион теперь встроены в само имя бакета. Как только злоумышленник получает идентификатор аккаунта цели, он может объединить его со словарём и систематически формировать валидные URL бакетов — а S3 подтвердит наличие каждого из них, даже если бакет приватный. Сам факт ответа — уже полезная разведка.
Bucky использует именно это. Основываясь на исследовании от Pwned Labs, он сначала восстанавливает 12-значный идентификатор аккаунта из доступного бакета с помощью техники s3-account-search, а затем перебирает шаблон {name}-{accountID}-{region}-an, чтобы раскрыть более широкий S3-след цели.
s3:ListBucket или s3:GetObject на целевой бакетsts:AssumeRole для этой роли, передавая встроенную политику сессии с условием s3:ResourceAccount, например "1*"1, вызов HeadBucket проходит успешно; в противном случае возвращается 403Для этого требуется не более 120 вызовов API (12 позиций × 10 цифр), и обычно всё выполняется менее чем за минуту.
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
Эта команда загружает и устанавливает последнюю версию из репозитория.
Перед использованием bucky вам потребуется роль IAM в вашем аккаунте AWS, которая имеет доступ к целевому бакету S3. Целевой бакет должен быть общедоступным или иметь политику бакета, разрешающую доступ из вашего аккаунта.
Создайте trust-policy.json — она разрешает вашему пользователю IAM принимать роль:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<YOUR_ACCOUNT_ID>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Замените
<YOUR_ACCOUNT_ID>на ваш 12-значный идентификатор аккаунта AWS. Вы можете ограничить действие определенным пользователем или ролью IAM вместо:root.
Создайте s3-policy.json — роли нужен широкий доступ на чтение S3 (условие s3:ResourceAccount во встроенной политике сессии bucky обрабатывает фильтрацию на уровне аккаунта):
{
"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
# Вывод: arn:aws:iam::123456789012:role/bucky-role
Если ваш пользователь IAM ещё не имеет разрешения sts:AssumeRole, добавьте его:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/bucky-role"
}
]
}
Основной способ использования bucky — перечислить идентификатор аккаунта из известного бакета, затем одним заходом произвести фаззинг для поиска дополнительных бакетов:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket \
--wordlist wordlists/default.txt \
--access-key AKIA... \
--secret-key wJal...
С известным ключом объекта (повышает надёжность):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket s3://target-bucket/index.html \
--wordlist wordlists/default.txt \
--workers 20
Несколько бакетов (через запятую):
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket bucket1,bucket2,bucket3 \
--wordlist wordlists/default.txt
Несколько бакетов из файла:
bucky \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket-file targets.txt \
--wordlist wordlists/default.txt
Сохранение результатов в JSON:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Вывод:
=== 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
Если вам нужен только идентификатор аккаунта:
bucky enum \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--bucket target-bucket
Несколько бакетов и вывод JSON также работают с подкомандами:
bucky enum --bucket bucket1,bucket2 --json
bucky enum --bucket-file targets.txt --json --output results.json
Если у вас уже есть идентификатор аккаунта и вы хотите найти бакеты:
bucky fuzz \
--role-arn arn:aws:iam::123456789012:role/bucky-role \
--account-id 675351422352 \
--wordlist wordlists/default.txt \
--workers 20
Все флаги можно задать через переменные окружения. Если заданы и флаг, и переменная, приоритет у флага.
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=wJal...
export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role
# Теперь достаточно указать цель
bucky --bucket target-bucket --wordlist wordlists/default.txt
Bucky поставляется со словарём по умолчанию wordlists/default.txt, содержащим около 300 распространённых шаблонов имён бакетов 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, , )Для целевых кампаний сгенерируйте собственный словарь, добавив имя организации в начало:
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
Подходит любой словарь, совместимый с такими инструментами, как ffuf или gobuster. Формат: одно имя бакета на строку, комментарии #, пустые строки игнорируются.
| Команда | Описание |
|---|---|
bucky | Полный рабочий процесс — перечислить идентификатор аккаунта, затем произвести фаззинг для поиска дополнительных бакетов |
bucky enum | Перечислить 12-значный идентификатор аккаунта из известного бакета |
bucky fuzz |
Глобальные флаги (все команды):
bucky (полный рабочий процесс):
| Флаг | Описание |
|---|---|
bucky enum:
| Флаг | Описание |
|---|---|
--bucket | Целевые бакеты S3, через запятую |
--bucket-file | Файл с именами/URL бакетов, по одному на строку |
bucky fuzz:
| Флаг | Описание |
|---|---|
Флаги --bucket и --bucket-file принимают несколько форматов. Bucky автоматически извлекает имя бакета (и опционально ключ) из:
| Формат | Пример |
|---|---|
| Простое имя | my-bucket |
| S3 URI | s3://my-bucket/path/to/key |
Несколько бакетов можно передать через запятую с помощью --bucket:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
Или перечислить по одному на строку в файле через --bucket-file:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
Когда несколько бакетов соответствуют одному и тому же идентификатору аккаунта, bucky удаляет дубликаты и запускает фаззинг только один раз для каждого уникального аккаунта.
Используйте --json, чтобы сохранить результаты в файл JSON. Имя файла по умолчанию — bucky-{uuid}.json в текущей директории, или укажите путь с помощью --output:
bucky --bucket target-bucket --wordlist wordlists/default.txt --json
bucky --bucket target-bucket --wordlist wordlists/default.txt --json --output results.json
Формат вывода:
{
"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 автоматически определяет регион целевых бакетов. Когда S3 возвращает перенаправление 301 (бакет находится в регионе, отличном от указанного в --region), bucky определяет правильный регион через HTTP-заголовок ответа x-amz-bucket-region и кеширует его для всех последующих запросов. Ручная настройка региона для целевого бакета не требуется.
Если у вас есть вопросы или отзывы о Genzai, или вы просто хотите связаться со мной, не стесняйтесь писать через LinkedIn или Email.
| Переменная | Флаг | Описание |
|---|
AWS_ACCESS_KEY_ID | --access-key | Идентификатор ключа доступа AWS |
AWS_SECRET_ACCESS_KEY | --secret-key | Секретный ключ доступа AWS |
AWS_SESSION_TOKEN | --session-token | Токен сессии AWS (для временных учётных данных) |
AWS_REGION | --region | Регион AWS (по умолчанию: us-east-1) |
AWS_DEFAULT_REGION | --region | Запасной, если AWS_REGION не задан |
AWS_PROFILE | --profile | Именованный профиль AWS из ~/.aws/credentials |
BUCKY_ROLE_ARN | --role-arn | ARN роли IAM для принятия |
BUCKY_BUCKET | --bucket | Имя целевого бакета S3 |
BUCKY_ACCOUNT_ID | --account-id | Идентификатор целевого аккаунта AWS (только для fuzz) |
BUCKY_WORDLIST | --wordlist | Путь к файлу словаря |
BUCKY_WORKERS | --workers | Количество конкурентных воркеров фаззинга (по умолчанию: 10) |
build-outputdocker-images| Произвести фаззинг имён бакетов по известному идентификатору аккаунта |
| Флаг | Описание |
|---|
--access-key | Идентификатор ключа доступа AWS |
--secret-key | Секретный ключ доступа AWS |
--session-token | Токен сессии AWS |
--region | Регион AWS (по умолчанию: us-east-1) |
--profile | Именованный профиль AWS |
--role-arn | ARN роли IAM для принятия |
--json | Сохранить результаты в файл JSON |
--output | Путь к файлу JSON для вывода (по умолчанию: bucky-{uuid}.json) |
--bucket| Целевые бакеты S3, через запятую |
--bucket-file | Файл с именами/URL бакетов, по одному на строку |
--wordlist | Путь к файлу словаря |
--workers | Количество конкурентных воркеров (по умолчанию: 10) |
--account-id |
| Целевой 12-значный идентификатор аккаунта AWS |
--wordlist | Путь к файлу словаря |
--workers | Количество конкурентных воркеров (по умолчанию: 10) |
--regions | Список регионов через запятую для мутаций имён |
| 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 |