
S3アカウントIDの列挙とバケットディスカバリーツール
S3アカウントIDの列挙とバケット発見ツール
1つのアクセス可能なS3バケットを指定すると、buckyはその所有者の12桁のAWSアカウントIDを抽出し、ワードリストに対してバケット名をファジングすることで同じアカウントに属する追加のバケットを発見します。すべて1つのコマンドで行えます。
s3:ResourceAccount IAM条件キーを使用して、インラインSTSセッションポリシーを介して12桁のAWSアカウントIDを1桁ずつブルートフォースします。当初、S3バケット名は単一のグローバル名前空間を共有しており、バケットスクワッティング(攻撃者が組織が作成すると予想される名前を先取りすること)を引き起こしました。AWSはこれに対処するために、アカウントリージョナル名前空間(各バケットをその所有者アカウントとリージョンに関連付ける命名スキーム)を展開しました:
{name}-{accountID}-{region}-an
myapp-123456789123-eu-north-1-anというバケットはhttps://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.comに存在します。AWSは現在新しいバケットにこの形式を推奨していますが、まだデフォルトではありません。(新しい名前空間がバケットスクワッティングをどのように撲滅するかの背景については、One Cloud Pleaseを参照してください。)
トレードオフとして、アカウントIDとリージョンがバケット名自体に組み込まれるようになりました。攻撃者がターゲットのアカウントIDを入手すると、ワードリストと組み合わせて有効なバケットURLを体系的に構築でき、S3はバケットがプライベートであっても各バケットが存在するかどうかを確認します。それだけでも有用な偵察となります。
Buckyはまさにこれを利用しています。Pwned Labsの研究に基づき、まずs3-account-search技術を使用してアクセス可能なバケットから12桁のアカウントIDを回復し、その後{name}-{accountID}-{region}-anパターンをブルートフォースしてターゲットのより広範なS3フットプリントを明らかにします。
s3:ListBucketまたはs3:GetObjectを持つIAMロールを作成します。sts:AssumeRoleを呼び出し、"1*"のようなs3:ResourceAccount条件を持つインラインセッションポリシーを渡します。1で始まる場合、HeadBucket呼び出しは成功します。それ以外の場合は403を返します。これには最大120回のAPI呼び出し(12桁×10数字)が必要で、通常は1分以内に完了します。
go installを使用go 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を使用する前に、ターゲットS3バケットにアクセスできる自分のAWSアカウントにIAMロールが必要です。ターゲットバケットは公開アクセス可能であるか、あなたのアカウントからのアクセスを許可するバケットポリシーが必要です。
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アカウントIDに置き換えてください。プリンシパルを:rootの代わりに特定のIAMユーザーまたはロールARNにスコープできます。
s3-policy.jsonを作成します。このロールには広範なS3読み取りアクセスが必要です(buckyのインラインセッションポリシー内のs3:ResourceAccount条件がアカウントレベルのフィルタリングを処理します):
{
"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の主な使用方法 — 既知のバケットからアカウントIDを列挙し、その後一挙にさらにバケットをファジングします:
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
アカウントIDのみが必要な場合:
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
すでにアカウントIDを持っていてバケットを発見したい場合:
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などのツールと互換性のあるワードリストが使用できます。形式:1行に1つのバケット名、#はコメント、空行は無視されます。
| コマンド | 説明 |
|---|---|
bucky | 完全ワークフロー — アカウントIDを列挙し、さらにバケットをファジング |
bucky enum | 既知のバケットから12桁のアカウントIDを列挙 |
bucky fuzz | 既知のアカウントIDに対してバケット名をファジング |
グローバルフラグ(すべてのコマンド):
bucky(完全ワークフロー):
| フラグ | 説明 |
|---|---|
--bucket | ターゲットS3バケット(カンマ区切り) |
bucky enum:
| フラグ | 説明 |
|---|---|
--bucket | ターゲットS3バケット(カンマ区切り) |
--bucket-file | バケット名/URLが1行に1つずつ書かれたファイル |
bucky fuzz:
| フラグ | 説明 |
|---|---|
--account-id | ターゲットの12桁AWSアカウントID |
--bucketフラグと--bucket-fileは複数の入力形式を受け入れます。Buckyは自動的にバケット名(およびオプションのキー)を次の形式から抽出します:
| 形式 | 例 |
|---|---|
| プレーン名 | my-bucket |
| S3 URI | s3://my-bucket/path/to/key |
| バーチャルホストURL |
複数のバケットは--bucketでカンマ区切りで渡せます:
--bucket bucket1,s3://bucket2/key,https://bucket3.s3.amazonaws.com/
または--bucket-fileでファイルに1行1つずつリストします:
my-bucket
s3://another-bucket/index.html
https://third.s3.us-east-1.amazonaws.com/
複数のバケットが同じアカウントIDに解決される場合、buckyは重複を排除し、一意のアカウントごとにファジングを1回だけ実行します。
--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はx-amz-bucket-region HTTPレスポンスヘッダーを介して正しいリージョンを解決し、後続のすべてのリクエストのためにキャッシュします。ターゲットバケットに手動でリージョン設定を行う必要はありません。
Genzaiに関するご質問やフィードバック、または私との連絡をご希望の場合は、LinkedInやメールでお気軽にご連絡ください。
| 変数 | フラグ | 説明 |
|---|
AWS_ACCESS_KEY_ID | --access-key | AWSアクセスキーID |
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/credentials からのAWS名前付きプロファイル |
BUCKY_ROLE_ARN | --role-arn | 引き受けるIAMロールのARN |
BUCKY_BUCKET | --bucket | ターゲットS3バケット名 |
BUCKY_ACCOUNT_ID | --account-id | ターゲットAWSアカウントID(fuzzのみ) |
BUCKY_WORDLIST | --wordlist | ワードリストファイルへのパス |
BUCKY_WORKERS | --workers | 同時ファジングワーカー数(デフォルト: 10) |
build-outputdocker-images| フラグ | 説明 |
|---|
--access-key | AWSアクセスキーID |
--secret-key | AWSシークレットアクセスキー |
--session-token | AWSセッショントークン |
--region | AWSリージョン(デフォルト: us-east-1) |
--profile | AWS名前付きプロファイル |
--role-arn | 引き受けるIAMロールのARN |
--json | 結果をJSONファイルに保存 |
--output | JSON出力ファイルのパス(デフォルト: bucky-{uuid}.json) |
--bucket-file | バケット名/URLが1行に1つずつ書かれたファイル |
--wordlist | ワードリストファイルへのパス |
--workers | 同時ワーカー数(デフォルト: 10) |
--wordlist | ワードリストファイルへのパス |
--workers | 同時ワーカー数(デフォルト: 10) |
--regions | 名前の変異のためのカンマ区切りのリージョン |
https://my-bucket.s3.us-west-2.amazonaws.com/key| パス形式URL | https://s3.us-west-2.amazonaws.com/my-bucket/key |