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 데이터 이벤트 사용).
사전 요구 사항
s3:GetBucketPolicy,s3:GetBucketAcl,s3:GetBucketPublicAccessBlock,s3:GetEncryptionConfiguration,s3:ListAllMyBuckets권한이 있는 자격 증명으로 구성된 AWS CLI v2- Prowler 설치 (
pip install prowler) - 자동화된 CIS 벤치마크 검사용 - S3audit 또는 유사한 열거 도구 - 빠른 공용 버킷 탐지용
- 여러 계정을 감사하는 경우 AWS Organizations 액세스 권한
- 맞춤형 감사 스크립트를 위한 Python 3.8+ 및 boto3
워크플로우
1단계: 모든 S3 버킷 및 계정 수준 공용 차단 액세스 열거
먼저 계정 수준의 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' 경고: {effect} with 와일드카드 주체')
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 관련 검사 실행
CIS AWS Foundations Benchmark에 맞춰 Prowler의 S3 중심 검사를 실행합니다.
# 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단계: S3 공개 및 교차 계정 결과에 IAM Access Analyzer 사용
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 (액세스 제어 목록) | AWS 계정 또는 AllUsers, AuthenticatedUsers와 같은 사전 정의된 그룹에 권한을 부여하는 레거시 S3 액세스 제어 메커니즘 |
| IAM Access Analyzer | 리소스 정책을 분석하여 외부 엔터티 또는 공개적으로 공유된 리소스를 식별하는 AWS 서비스 |
| 서버 측 암호화 | 데이터를 디스크에 쓰기 전에 SSE-S3, SSE-KMS 또는 SSE-C를 사용하여 S3가 객체 수준에서 적용하는 암호화 |
| CIS AWS Foundations Benchmark | S3 버킷 구성에 대한 특정 제어 항목이 포함된 CIS(Center for Internet Security)의 보안 모범 사례 표준 |
도구 및 시스템
- AWS CLI: S3 버킷 구성, 정책, ACL 및 암호화 설정을 쿼리하기 위한 기본 인터페이스
- Prowler: CIS, PCI DSS, HIPAA 제어에 맞춰 50개 이상의 S3 관련 검사를 제공하는 오픈 소스 보안 도구
- IAM Access Analyzer: 외부 액세스를 허용하는 리소스 정책을 지속적으로 모니터링하는 AWS 네이티브 서비스
- S3audit: 계정 내 공용 S3 버킷을 빠르게 열거하기 위한 경량 도구
- ScoutSuite: S3 구성 데이터를 수집하고 위험 점수가 포함된 HTML 보고서를 생성하는 멀티 클라우드 감사 도구
일반적인 시나리오
시나리오: 고객 데이터가 포함된 공개 읽기 가능 버킷 식별
컨텍스트: 보안 엔지니어가 공개적으로 액세스 가능한 S3 버킷에 대한 Trusted Advisor 경고를 받습니다. 해당 버킷은 데모용으로 개발 팀이 생성했으며 잠금 설정되지 않았습니다.
접근 방식:
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
문제: 정책이 VPC/IP 조건 없이 Principal "*"로 s3:GetObject 허용
위험: 파트너 액세스용으로 의도되었지만 버킷 이름을 아는 모든 사람이 액세스 가능
수정: aws:SourceVpce 또는 aws:SourceIp 조건을 추가하여 액세스 제한
요약:
공용 액세스가 있는 버킷: 3 / 47
암호화되지 않은 버킷: 5 / 47
버전 관리되지 않은 버킷: 12 / 47
액세스 로깅되지 않은 버킷: 18 / 47
과도하게 광범위한 정책이 있는 버킷: 7 / 47