umair9747/bucky

GitHub: umair9747/bucky

从单个可访问的 S3 bucket 枚举 AWS 账户 ID 并发现同账户下其他 bucket 的安全侦察工具。

Stars: 0 | Forks: 0

Bucky

An S3 account ID enumeration and bucket discovery tool




给定一个可访问的 S3 bucket,bucky 可以提取拥有该 bucket 的 12 位 AWS account ID,然后通过使用词表对 bucket 名称进行模糊测试来发现属于同一账户的其他 bucket —— 所有这些只需一条命令。 ## 功能介绍 1. **枚举账户 ID (Account ID)** — 使用 `s3:ResourceAccount` IAM 条件键,通过内联 STS 会话策略逐位暴力破解 12 位 AWS 账户 ID 2. **发现更多 bucket** — 使用并发 worker 对词表中的 bucket 名称进行模糊测试,以查找同一账户拥有的其他 bucket 3. **报告所有信息** — 账户 ID、bucket 区域以及所有发现的 bucket ## 为什么这很重要 S3 bucket 名称最初共享一个单一的全局命名空间,这导致了 **bucketsquatting**(bucket 抢注)现象——攻击者可以抢注他们预计组织会创建的名称。AWS 通过推出 **account-regional namespaces**(账户-区域命名空间)解决了这个问题,这是一种将每个 bucket 绑定到其所属账户和区域的命名方案: ``` {name}-{accountID}-{region}-an ``` 一个名为 `myapp-123456789123-eu-north-1-an` 的 bucket 将位于 `https://myapp-123456789123-eu-north-1-an.s3.eu-north-1.amazonaws.com`。AWS 现在建议新 bucket 使用此格式,尽管它尚未成为默认格式。(有关新命名空间如何消除 bucketsquatting 的背景知识,请参阅 [One Cloud Please](https://onecloudplease.com/blog/bucketsquatting-is-finally-dead)。) 权衡之处在于,账户 ID 和区域现在已融入 bucket 名称本身。一旦攻击者获得目标的账户 ID,他们就可以将其与词表配对,系统地构建有效的 bucket URL —— 即使 bucket 是私有的,S3 也会确认每个 URL 是否存在。仅此响应就是有用的侦察信息。 Bucky 正是利用了这一点。借鉴 [Pwned Labs](https://blog.pwnedlabs.io/a-new-s3-namespace-and-a-new-problem) 的研究,它首先使用 [s3-account-search](https://github.com/WeAreCloudar/s3-account-search) 技术从任何可访问的 bucket 中恢复 12 位账户 ID,然后对 `{name}-{accountID}-{region}-an` 模式进行暴力破解,以揭开目标更广泛的 S3 足迹。 ## 技术原理 1. 您在**您自己的** AWS 账户中创建一个 IAM role,该 role 对目标 bucket 拥有 `s3:ListBucket` 或 `s3:GetObject` 权限 2. 您对该 role 调用 `sts:AssumeRole`,并传递一个带有 `s3:ResourceAccount` 条件(如 `"1*"`)的 **inline session policy** 3. 如果目标 bucket 的所属账户以 `1` 开头,则 `HeadBucket` 调用成功;否则返回 403 4. 对每个数字位置(0–9)重复此操作,直到发现所有 12 位数字 5. 内联会话策略充当权限边界 —— 它与 role 的权限相交,因此仅在条件匹配时才授予访问权限 这最多需要 **120 次 API 调用**(12 个位置 × 10 个数字),通常在一分钟内完成。 ## 安装 ### 使用 `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 ``` 这将拉取并安装存储库中的最新版本。 ## 前置条件:IAM Role 设置 在使用 bucky 之前,您需要在**您自己的 AWS 账户**中拥有一个可以访问目标 S3 bucket 的 IAM role。目标 bucket 必须公开可访问,或者具有允许从您的账户访问的 bucket 策略。 ### 步骤 1:创建信任策略 创建 `trust-policy.json` —— 这允许您的 IAM user 担任该 role: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam:::root" }, "Action": "sts:AssumeRole" } ] } ``` ### 步骤 2:创建权限策略 创建 `s3-policy.json` —— 该 role 需要广泛的 S3 读取权限(bucky 内联会话策略中的 `s3:ResourceAccount` 条件负责账户级别过滤): ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject" ], "Resource": "*" } ] } ``` ### 步骤 3:创建 Role ``` 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 ``` ### 步骤 4:获取 Role ARN ``` aws iam get-role --role-name bucky-role --query 'Role.Arn' --output text # 输出: arn:aws:iam::123456789012:role/bucky-role ``` ### 步骤 5:确保拥有 AssumeRole 权限 如果您的 IAM user 尚未拥有 `sts:AssumeRole` 权限,请附加该权限: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam:::role/bucky-role" } ] } ``` ## 使用方法 ### 完整工作流(默认) 使用 bucky 的主要方式 —— 从已知 bucket 枚举账户 ID,然后一次性模糊测试以发现更多 bucket: ``` 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 ``` 多个 bucket(以逗号分隔): ``` bucky \ --role-arn arn:aws:iam::123456789012:role/bucky-role \ --bucket bucket1,bucket2,bucket3 \ --wordlist wordlists/default.txt ``` 从文件读取多个 bucket: ``` 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 ``` 多个 bucket 和 JSON 输出也适用于子命令: ``` bucky enum --bucket bucket1,bucket2 --json bucky enum --bucket-file targets.txt --json --output results.json ``` ### 仅模糊测试 如果您已经拥有账户 ID 并想要发现 bucket: ``` bucky fuzz \ --role-arn arn:aws:iam::123456789012:role/bucky-role \ --account-id 675351422352 \ --wordlist wordlists/default.txt \ --workers 20 ``` ## 环境变量 所有标志都可以通过环境变量设置。如果两者都设置了,标志优先。 | 变量 | 标志 | 描述 | |---|---|---| | `AWS_ACCESS_KEY_ID` | `--access-key` | AWS access key ID | | `AWS_SECRET_ACCESS_KEY` | `--secret-key` | AWS secret access key | | `AWS_SESSION_TOKEN` | `--session-token` | AWS session token(用于临时凭证) | | `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 role 的 ARN | | `BUCKY_BUCKET` | `--bucket` | 目标 S3 bucket 名称 | | `BUCKY_ACCOUNT_ID` | `--account-id` | 目标 AWS 账户 ID(仅限 `fuzz`) | | `BUCKY_WORDLIST` | `--wordlist` | 词表文件路径 | | `BUCKY_WORKERS` | `--workers` | 并发模糊测试 worker(默认:`10`) | ### 使用环境变量的示例 ``` export AWS_ACCESS_KEY_ID=AKIA... export AWS_SECRET_ACCESS_KEY=wJal... export BUCKY_ROLE_ARN=arn:aws:iam::123456789012:role/bucky-role # 现在只需指定 target bucky --bucket target-bucket --wordlist wordlists/default.txt ``` ## 词表 Bucky 附带了一个位于 `wordlists/default.txt` 的默认词表,包含约 300 个常见的 S3 bucket 命名模式: - 通用名称(`backups`、`logs`、`data`、`assets`、`uploads`) - AWS 服务模式(`cloudtrail-logs`、`terraform-state`、`lambda-artifacts`) - 环境变体(`prod-logs`、`staging-data`、`dev-backups`) - 应用程序模式(`api`、`web-assets`、`cdn-origin`) - 基础设施(`ci-artifacts`、`build-output`、`docker-images`) ### 自定义词表 对于针对性强的任务,通过添加组织名称前缀来生成自定义词表: ``` 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 等工具的词表均可使用。格式:每行一个 bucket 名称,支持 `#` 注释,忽略空行。 ## 命令参考 | 命令 | 描述 | |---|---| | `bucky` | **完整工作流** — 枚举账户 ID,然后模糊测试以发现更多 bucket | | `bucky enum` | 从已知 bucket 枚举 12 位账户 ID | | `bucky fuzz` | 对已知的账户 ID 进行 bucket 名称模糊测试 | ### 标志 **全局标志**(所有命令): | 标志 | 描述 | |---|---| | `--access-key` | AWS access key ID | | `--secret-key` | AWS secret access key | | `--session-token` | AWS session token | | `--region` | AWS 区域(默认:`us-east-1`) | | `--profile` | AWS 命名配置文件 | | `--role-arn` | 要担任的 IAM role 的 ARN | | `--json` | 将结果保存到 JSON 文件 | | `--output` | JSON 输出文件路径(默认:`bucky-{uuid}.json`) | **`bucky`(完整工作流): | 标志 | 描述 | |---|---| | `--bucket` | 目标 S3 bucket,以逗号分隔 | | `--bucket-file` | 包含 bucket 名称/URL 的文件,每行一个 | | `--wordlist` | 词表文件路径 | | `--workers` | 并发 worker(默认:`10`) | **`bucky enum`:** | 标志 | 描述 | |---|---| | `--bucket` | 目标 S3 bucket,以逗号分隔 | | `--bucket-file` | 包含 bucket 名称/URL 的文件,每行一个 | **`bucky fuzz`:** | 标志 | 描述 | |---|---| | `--account-id` | 目标 12 位 AWS 账户 ID | | `--wordlist` | 词表文件路径 | | `--workers` | 并发 worker(默认:`10`) | | `--regions` | 用于名称变异的区域,以逗号分隔 | ## Bucket 输入格式 `--bucket` 标志和 `--bucket-file` 接受多种输入格式。Bucky 会自动从以下格式中提取 bucket 名称(和可选键): | 格式 | 示例 | |---|---| | 纯名称 | `my-bucket` | | S3 URI | `s3://my-bucket/path/to/key` | | 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` | 可以通过 `--bucket` 以逗号分隔传递多个 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/ ``` 当多个 bucket 解析到同一个账户 ID 时,bucky 会去重,并仅对每个唯一账户运行一次模糊测试。 ## JSON 输出 使用 `--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" ] } ] } ``` ## Bucket 区域处理 Bucky 自动检测目标 bucket 的区域。当 S3 返回 301 重定向(bucket 位于与 `--region` 不同的区域)时,bucky 通过 `x-amz-bucket-region` HTTP 响应头解析正确的区域,并将其缓存用于所有后续请求。无需为目标 bucket 配置手动区域。 ## 联系我们! 如果您对 Genzai 有任何问题或反馈,或者只是想与我联系,请随时通过 LinkedInEmail 与我联系。
标签:Amazon Web Services, AWS S3, Bucket Security, Bucky, EVTX分析, ID枚举, Python, S3 存储桶, 信息泄露, 存储桶发现, 密码管理, 开源安全工具, 无后门, 日志审计, 账户枚举, 足迹分析, 逆向工程平台