審計 AWS S3 儲存貯體權限 是做什麼的?
使用時機
- 對 AWS 環境進行安全評估以識別公開曝露的資料時
- 導入新的 AWS 帳戶並為儲存資源建立安全基準時
- 回應來自 AWS Trusted Advisor 或 Security Hub 關於潛在 S3 資料曝露的警報時
- 當合規框架(SOC 2、PCI DSS、HIPAA)要求定期審查資料存取控制時
- 發生資料外洩或憑證外洩,需要立即審查所有可存取的 S3 資源時
請勿使用 於審計非 AWS 物件儲存(請使用供應商特定工具)、即時監控(請使用搭配 Lambda 的 S3 事件通知),或審計 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 儲存貯體及帳戶級別的 Block Public Access
首先檢查帳戶級別的 S3 Block Public Access 設定,然後列出所有儲存貯體及其區域。
# 檢查帳戶級別的 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:檢查每個儲存貯體的 Public Access Block 與 ACL 配置
遍歷所有儲存貯體以評估其個別的公開存取封鎖設定和 ACL 授予。
# 檢查每個儲存貯體的 Block Public Access 設定
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"
# 檢查 ACL 中是否有公開授予
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 政策 ==="
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' WARNING: {effect} 包含萬用字元主體')
print(f' Actions: {stmt.get(\"Action\", \"\")}')
print(f' Condition: {stmt.get(\"Condition\", \"NONE\")}')
"
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 基礎安全基準。
# 執行 Prowler S3 特定檢查
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 識別對外公開或與外部共享的儲存貯體。
# 列出 S3 的 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:生成審計報告並進行補救
將結果彙整成可操作的報告,並對關鍵問題進行補救。
# 快速補救:對儲存貯體啟用 Block Public Access
aws s3api put-public-access-block \
--bucket TARGET_BUCKET \
--public-access-block-configuration \
'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'
# 使用 SSE-S3 啟用預設加密
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 和政策以防止公開存取,無論個別資源配置如何 |
| 儲存貯體政策 | 附加到儲存貯體的 JSON 格式資源政策,定義誰可以存取該儲存貯體以及他們可以執行哪些操作 |
| ACL (存取控制清單) | 舊版 S3 存取控制機制,授予 AWS 帳戶或預定義群組(如 AllUsers 或 AuthenticatedUsers)權限 |
| IAM Access Analyzer | AWS 服務,用於分析資源政策以識別與外部實體或公眾共享的資源 |
| 伺服器端加密 | S3 在物件層級應用的加密,使用 SSE-S3、SSE-KMS 或 SSE-C,在將資料寫入磁碟前進行加密 |
| CIS AWS 基礎安全基準 | 來自網際網路安全中心的安全最佳實踐標準,包含針對 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並發現授予AllUsersREAD權限 - 檢查
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
問題:透過 ACL 授予 AllUsers 群組 READ 權限
風險:任何網際網路使用者都可以列出並下載儲存貯體內容
資料敏感性:包含面向客戶但非敏感的行銷資產
補救措施:移除 AllUsers ACL 授予,啟用 Block Public Access
[S3-002] 儲存貯體政策中的萬用字元主體
儲存貯體:data-exchange-partner
問題:政策允許 s3:GetObject,主體為 "*" 且無 VPC/IP 條件
風險:預期供合作夥伴存取,但任何知道儲存貯體名稱的人都可以存取
補救措施:新增 aws:SourceVpce 或 aws:SourceIp 條件以限制存取
摘要:
具有公開存取的儲存貯體: 3 / 47
未加密的儲存貯體: 5 / 47
無版本控制的儲存貯體: 12 / 47
無存取日誌記錄的儲存貯體: 18 / 47
政策過度寬鬆的儲存貯體: 7 / 47