| name | auditing-aws-s3-bucket-permissions |
| description | 使用 AWS CLI、S3audit 和 Prowler,系统性审计 AWS S3 存储桶权限,识别可公开访问的存储桶、 过度宽松的 ACL、错误配置的存储桶策略和缺失的加密设置,以强制执行最小权限数据访问控制。
|
| domain | cybersecurity |
| subdomain | cloud-security |
| tags | ["cloud-security","aws","s3","bucket-permissions","data-protection","access-control"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
审计 AWS S3 存储桶权限
适用场景
- 对 AWS 环境进行安全评估时,识别公开暴露的数据
- 加入新 AWS 账户时,为存储资源建立安全基线
- 响应来自 AWS Trusted Advisor 或 Security Hub 的潜在 S3 数据暴露告警时
- 合规框架(SOC 2、PCI DSS、HIPAA)要求定期审查数据访问控制时
- 发生泄露或凭据失陷后,需要立即审查所有可访问 S3 资源时
不适用于:审计非 AWS 对象存储(使用提供商特定工具)、实时监控(使用带 Lambda 的 S3 Event Notifications)或审计 S3 访问模式(使用 S3 Access Analyzer 或 CloudTrail S3 数据事件)。
前置条件
- AWS CLI v2 配置凭据,具备
s3:GetBucketPolicy、s3:GetBucketAcl、s3:GetBucketPublicAccessBlock、s3:GetEncryptionConfiguration 和 s3:ListAllMyBuckets 权限
- 安装 Prowler(
pip install prowler)用于自动 CIS 基准检查
- 安装 S3audit 或类似枚举工具,快速检测公开存储桶
- 跨多账户审计时需要访问 AWS Organizations
- Python 3.8+ 及 boto3,用于自定义审计脚本
工作流程
步骤 1:枚举所有 S3 存储桶及账户级别的公开访问阻止设置
首先检查账户级别的 S3 Block Public Access 设置,然后列出所有存储桶及其区域。
aws s3control get-public-access-block \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--output json
aws s3api list-buckets \
--query 'Buckets[*].[Name,CreationDate]' \
--output table
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
region=$(aws s3api get-bucket-location --bucket "$bucket" --query 'LocationConstraint' --output text)
echo "$bucket -> ${region:-us-east-1}"
done
步骤 2:检查每个存储桶的公开访问阻止和 ACL 配置
遍历所有存储桶,评估各自的公开访问阻止设置和 ACL 授权。
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
echo "=== $bucket ==="
aws s3api get-public-access-block --bucket "$bucket" 2>/dev/null || echo " 未配置 Block Public Access"
aws s3api get-bucket-acl --bucket "$bucket" \
--query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers` || Grantee.URI==`http://acs.amazonaws.com/groups/global/AuthenticatedUsers`]' \
--output json
done
步骤 3:分析存储桶策略中的过度宽松访问
审查存储桶策略中的通配符主体、缺少的条件以及允许广泛访问的语句。
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
policy=$(aws s3api get-bucket-policy --bucket "$bucket" --output text 2>/dev/null)
if [ -n "$policy" ]; then
echo "=== $bucket policy ==="
echo "$policy" | python3 -c "
import json, sys
policy = json.load(sys.stdin)
for stmt in policy.get('Statement', []):
principal = stmt.get('Principal', {})
effect = stmt.get('Effect', '')
if principal == '*' or principal == {'AWS': '*'}:
print(f' 警告: {effect} 使用通配符主体')
print(f' 操作: {stmt.get(\"Action\", \"\")}')
print(f' 条件: {stmt.get(\"Condition\", \"无\")}')
"
fi
done
步骤 4:验证加密和版本控制设置
检查所有存储桶是否启用了服务器端加密,并为数据保护配置了版本控制。
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
echo "=== $bucket ==="
aws s3api get-bucket-encryption --bucket "$bucket" 2>/dev/null \
&& echo " 加密: 已启用" \
|| echo " 加密: 未启用"
aws s3api get-bucket-versioning --bucket "$bucket" \
--query 'Status' --output text
aws s3api get-bucket-logging --bucket "$bucket" \
--query 'LoggingEnabled' --output text 2>/dev/null
done
步骤 5:运行 Prowler S3 专项检查
执行 Prowler 的 S3 专项检查,与 CIS AWS Foundations Benchmark 对齐。
prowler aws \
--checks s3_bucket_public_access \
s3_bucket_default_encryption \
s3_bucket_policy_public_write_access \
s3_bucket_server_access_logging_enabled \
s3_bucket_versioning_enabled \
s3_bucket_acl_prohibited \
-M json-ocsf \
-o ./prowler-s3-audit/
prowler aws --checks s3 -M csv -o ./prowler-s3-audit/
步骤 6:使用 IAM Access Analyzer 识别 S3 公开和跨账户发现
利用 IAM Access Analyzer 识别与外部实体或公开共享的存储桶。
aws accessanalyzer list-findings \
--analyzer-arn $(aws accessanalyzer list-analyzers --query 'analyzers[0].arn' --output text) \
--filter '{"resourceType": {"eq": ["AWS::S3::Bucket"]}}' \
--query 'findings[*].[resource,status,condition,principal]' \
--output table
aws accessanalyzer create-analyzer \
--analyzer-name s3-access-audit \
--type ACCOUNT
步骤 7:生成审计报告并进行修复
将发现汇编成可操作的报告,并对严重问题进行修复。
aws s3api put-public-access-block \
--bucket TARGET_BUCKET \
--public-access-block-configuration \
'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'
aws s3api put-bucket-encryption \
--bucket TARGET_BUCKET \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"alias/aws/s3"},"BucketKeyEnabled":true}]}'
aws s3api put-bucket-versioning \
--bucket TARGET_BUCKET \
--versioning-configuration Status=Enabled
核心概念
| 术语 | 定义 |
|---|
| S3 Block Public Access | 账户级别和存储桶级别的设置,覆盖 ACL 和策略,无论各资源单独配置如何,都可防止公开访问 |
| 存储桶策略(Bucket Policy) | 附加到存储桶的基于 JSON 的资源策略,定义谁可以访问存储桶以及可以执行哪些操作 |
| ACL(访问控制列表) | 旧版 S3 访问控制机制,向 AWS 账户或预定义组(如 AllUsers 或 AuthenticatedUsers)授权 |
| IAM Access Analyzer | AWS 服务,分析资源策略以识别与外部实体或公众共享的资源 |
| 服务器端加密(Server-Side Encryption) | S3 在将数据写入磁盘前,使用 SSE-S3、SSE-KMS 或 SSE-C 在对象级别应用的加密 |
| CIS AWS Foundations Benchmark | 互联网安全中心(Center for Internet Security)的安全最佳实践标准,包含 S3 存储桶配置的具体控制措施 |
工具与系统
- AWS CLI:查询 S3 存储桶配置、策略、ACL 和加密设置的主要接口
- Prowler:开源安全工具,含 50+ 项 S3 专项检查,与 CIS、PCI DSS 和 HIPAA 控制对齐
- IAM Access Analyzer:AWS 原生服务,持续监控授予外部访问的资源策略
- S3audit:轻量级工具,用于快速枚举账户内的公开 S3 存储桶
- ScoutSuite:多云审计工具,收集 S3 配置数据并生成风险评分 HTML 报告
常见场景
场景:识别包含客户数据的可公开读取存储桶
场景背景:安全工程师收到 Trusted Advisor 关于可公开访问 S3 存储桶的告警。该存储桶由开发团队为演示而创建,从未进行访问限制。
方法:
- 运行
aws s3api get-bucket-acl,发现对 AllUsers 的 READ 权限授权
- 检查
get-bucket-policy,发现带有 Principal: "*" 和 s3:GetObject 的策略
- 确认存储桶和账户级别均未启用 Block Public Access
- 枚举存储桶内容以评估数据敏感性
- 立即对存储桶启用 Block Public Access
- 审查 CloudTrail S3 数据事件,判断是否发生未授权访问
- 提交报告,包含时间线、数据清单和修复确认
常见陷阱:启用 Block Public Access 可能会破坏有意公开提供内容(如静态网站)的应用程序。应用限制前始终验证存储桶的预期用途。检查是否有 CloudFront 分发或其他服务依赖存储桶的公开访问。
输出格式
S3 存储桶权限审计报告
=====================================
账户: 123456789012 (生产环境)
日期: 2026-02-23
审计员: 安全工程团队
存储桶总数: 47
账户级别设置:
Block Public Access: 已启用(全部四项设置)
严重发现:
[S3-001] 通过 ACL 的公开读取访问
存储桶: marketing-assets-prod
问题: AllUsers 组通过 ACL 获得 READ 权限
风险: 任何互联网用户均可列出并下载存储桶内容
数据敏感性: 包含面向客户但非敏感的营销资产
修复: 移除 AllUsers ACL 授权,启用 Block Public Access
[S3-002] 存储桶策略中的通配符主体
存储桶: data-exchange-partner
问题: 策略允许 s3:GetObject,Principal 为 "*" 且无 VPC/IP 条件
风险: 本为合作伙伴访问设计,但任何知道存储桶名称的人均可访问
修复: 添加 aws:SourceVpce 或 aws:SourceIp 条件以限制访问
摘要:
有公开访问的存储桶: 3 / 47
未加密的存储桶: 5 / 47
未启用版本控制的存储桶: 12 / 47
未启用访问日志的存储桶: 18 / 47
策略过于宽松的存储桶: 7 / 47