Security Hub の指摘、駆逐してますか?
- とりあえず、Security Hub を有効化したけど、セキュリティスコアが低くて困っている…
- Security Hub の検出結果 (Findings) にどう対処すればよいのかわからない…
- S3 のセキュリティを強化したい…
そんな方々のために、本記事では Security Hub の S3 に関する指摘事項を一匹残らず駆逐する方法を解説します。
また、解説と合わせて、Security Hub に指摘されない S3 バケットを作成するための CloudFormation テンプレートも紹介していきます。
「解説はいいから早よ CloudFormation をよこせ」という方はこちらをどうぞ。
↓ ↓ ↓
CloudFormation を捧げよ!
本記事は 駆逐してやる!!AWS Security Hubの指摘を…この世から…一匹残らず!! ~ S3編 (CLI) ~ の CloudFormation 版です。CloudFormation 以外の内容(解説等)は同じです。
AWS Security Hub とは
一言でいうと、複数のAWSサービスのセキュリティアラートを集約して一元管理するためのサービスです。
セキュリティ標準 (Standards)
Security Hub は、AWS のベストプラクティスや業界標準に基づいたセキュリティチェック機能 を備えています。
投稿時点 (2022/03/21) では、以下の セキュリティ標準 (Standards) が用意されています。
- AWS 基礎セキュリティのベストプラクティス (AWS Foundational Security Best Practices)
- CIS AWS Foundations Benchmark
- Payment Card Industry Data Security Standard (PCI DSS)
コントロール (Controls)
セキュリティ標準に含まれる個々のチェック項目を コントロール (Controls) と呼びます。
例えば、AWS Foundational Security Best Practices には以下のようなコントロール (Controls) が含まれます。
- AWS Foundational Security Best Practices
- [S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります
- [S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります
・・・
検出結果 (Findings)
セキュリティチェックにより検出された結果を 検出結果 (Findings) と呼びます。
ただし、本記事ではわかりやすくするために 指摘 と表現します。
駆逐してやる!!
ここからは指摘の駆逐方法を解説していきます。
既存バケットの設定を変更する場合、変更による影響を十分に検証してください。
投稿内容を利用したことにより生じた損害について、著者は一切の責任を負いません。
AWS Foundational Security Best Practices
AWS Foundational Security Best Practices は名前のとおり、AWS における基礎的なベストプラクティスに基づいたセキュリティ標準です。
[S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります
[S3.1] S3 Block Public Access setting should be enabled
重大度:中
この指摘を駆逐するには、アカウントレベルのブロックパブリックアクセス設定を有効にします。
ブロックパブリックアクセス設定には、アカウントレベルとバケットレベルの2種類の設定が存在します。
[S3.1] はアカウントレベルの設定です。バケットレベルの設定は [S3.8] が該当します。
アカウントレベルの設定は、マネジメントコンソール、または、CLI で設定します。
CloudFormation では設定できません。
マネジメントコンソール
以下の画面から設定します。
Amazon S3 > このアカウントのブロックパブリックアクセス設定
CLI
以下のコマンドで設定します。
s3control put-public-access-block
INPUT_YAML=$(cat << EOS
AccountId: "${AWS_ACCOUNT_ID}"
PublicAccessBlockConfiguration:
BlockPublicAcls: true
IgnorePublicAcls: true
BlockPublicPolicy: true
RestrictPublicBuckets: true
EOS
)
aws s3control put-public-access-block --cli-input-yaml "$INPUT_YAML"
- ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。
参考
[S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります
[S3.2] S3 buckets should prohibit public read access
重大度:重大
この指摘の駆逐方法は [S3.8] に含まれます。
以下を参照してください。
- AWS Foundational Security Best Practices
[S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります
[S3.3] S3 バケットはパブリック書き込みアクセスを禁止する必要があります
[S3.3] S3 buckets should prohibit public write access
重大度:重大
この指摘の駆逐方法は [S3.8] に含まれます。
以下を参照してください。
- AWS Foundational Security Best Practices
[S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります
[S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります
[S3.4] S3 buckets should have server-side encryption enabled
重大度:中
この指摘を駆逐するには、S3 バケットのサーバー側の暗号化を有効にします。
デフォルトのサーバー側の暗号化は以下の2種類から選択できます。
- S3 で管理されたキーを使用する SSE-S3
- KMS に保存されたキーを使用する SSE-KMS
CloudFormation
BucketEncryption プロパティで設定します。
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID: !Ref EncryptionKeyId
BucketKeyEnabled: true
- EncryptionKeyId はパラメータです。暗号化に使用する KMS Key ID を指定します。
- BucketKeyEnabled はオプションですが、SSE-KMS の場合は有効化することをおすすめします。バケットキーを有効化することにより、S3 から KMS へのリクエストを減らし、コストを削減することができます。
参考
[S3.5] S3 バケットは、Secure Socket Layer を使用するためのリクエストが必要です
[S3.5] S3 buckets should require requests to use Secure Socket Layer
重大度:中
この指摘を駆逐するには、S3 バケットに対する操作が HTTPS リクエストのみを受け入れる(HTTP リクエストは拒否する)ように設定します。
CloudFormation
バケットポリシーに以下のステートメントを追加します。
ポイントは aws:SecureTransport です。
aws:SecureTransport が false の場合= HTTPS リクエストではない場合、S3 バケットおよびオブジェクトに対するすべての操作を拒否します。
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: DenyInsecureRequests
Effect: Deny
Principal: "*"
Action:
- s3:*
Resource:
- !Sub arn:aws:s3:::${Bucket}
- !Sub arn:aws:s3:::${Bucket}/*
Condition:
Bool:
aws:SecureTransport: false
参考
[S3.6] 他のユーザーに付与された Amazon S3 のアクセス許可AWSバケットポリシーのアカウントは制限する必要があります
[S3.6] Amazon S3 permissions granted to other AWS accounts in bucket policies should be restricted
重大度:高
この指摘は、他アカウントのユーザーやロールに対して、以下のいずれかの操作を明示的に許可している場合に指摘されます。
- s3:DeleteBucketPolicy
- s3:PutBucketAcl
- s3:PutBucketPolicy
- s3:PutEncryptionConfiguration
- s3:PutObjectAcl
つまり、他アカウントのユーザーやロールに対して、これらの操作を明示的に許可していなければ、指摘されることはありません。
なお、他アカウントのユーザーやロールに対する 明示的な拒否 を設定しておくと、意図せずに許可してしまうことを防ぐことができます。
CloudFormation
バケットポリシーに以下のステートメントを追加します。
ポイントは NotPrincipal です。
NotPrincipal に自アカウントIDを指定することにより、自アカウント以外=他アカウントに対する明示的な拒否を設定しています。
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: DenySensitiveActionsFromOtherAccounts
Effect: Deny
NotPrincipal:
AWS: !Ref AWS::AccountId
Action:
- s3:DeleteBucketPolicy
- s3:PutBucketAcl
- s3:PutBucketPolicy
- s3:PutEncryptionConfiguration
- s3:PutObjectAcl
Resource:
- !Sub arn:aws:s3:::${Bucket}
- !Sub arn:aws:s3:::${Bucket}/*
参考
[S3.7] (欠番)
[S3.7] は存在しません。欠番のようです。
[S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります
[S3.8] S3 Block Public Access setting should be enabled at the bucket level
重大度:高
この指摘を駆逐するには、バケットレベルのブロックパブリックアクセス設定を有効にします。
「[S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります」は、アカウントレベルの設定でしたが、こちらはバケットレベルの設定です。
アカウントレベルで設定していても、Security Hub はバケットレベルの設定も要求してきます。
CloudFormation
PublicAccessBlockConfiguration プロパティで設定します。
Bucket:
Type: AWS::S3::Bucket
Properties:
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
参考
[S3.9] S3 バケットサーバーアクセスログを有効にする必要があります
[S3.9] S3 bucket server access logging should be enabled
重大度:中
この指摘を駆逐するには、S3 バケットに対するアクセスログを有効にします。
ただし、アクセスログ保存用バケット自体のロギング設定は留意する必要があります。
以下のとおり、ソースバケット(ロギング対象)とターゲットバケット(ログ保存先)が同じ場合、いくつかの留意事項があるため、アクセスログ保存用バケット自体のロギングは設定しない判断が好ましいケースもあります。
この場合、アクセスログ保存用バケットに対する [S3.9] の指摘は抑制するのがよいでしょう。
ソースバケットとターゲットバケットが同じである場合、バケットに書き込まれるログに関する追加のログが作成されます。これは、ストレージの請求額がいくらか増える可能性があるため、望ましくない場合があります。また、ログに関する追加のログのために、必要なログを見つけにくくなります。
引用:https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ServerLogs.html
CloudFormation
LoggingConfiguration プロパティで設定します。
Bucket:
Type: AWS::S3::Bucket
Properties:
LoggingConfiguration:
DestinationBucketName: !Ref LoggingBucketName
LogFilePrefix: !Ref BucketName
- LoggingBucketName はパラメータです。ログ保存先のバケット名を指定します。
- LogFilePrefix の指定はオプションですが、複数バケットのアクセスログをひとつのバケットに集約する際に、どのバケットのアクセスログかを判別できるよう、バケット名をプレフィックスとして設定することをおすすめします。
参考
CIS AWS Foundations Benchmark
CIS AWS Foundations Benchmark は CIS (Center of Internet Security) のベンチマークに基づいたセキュリティ標準です。
2.3 — CloudTrail ログが記録する S3 バケットがパブリックにアクセスできないことを確認します
2.3 – Ensure the S3 bucket CloudTrail logs to is not publicly accessible
重大度:重大
この指摘を駆逐するには、CloudTrail ログバケットに対して、ブロックパブリックアクセスを設定します。
ブロックパブリックアクセスの設定方法は、以下を参照してください。
- AWS Foundational Security Best Practices
[S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります
2.6 — CloudTrail S3 バケットアクセスログ記録が CloudTrail S3 バケットで有効になっていることを確認します
2.6 – Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket
重大度:低
この指摘を駆逐するには、CloudTrail ログバケットに対して、アクセスログ記録を設定します。
アクセスログ記録の設定方法は、以下を参照してください。
- AWS Foundational Security Best Practices
[S3.9] S3 バケットサーバーアクセスログを有効にする必要があります
Payment Card Industry Data Security Standard (PCI DSS)
Payment Card Industry Data Security Standard (PCI DSS) は、クレジットカード業界のセキュリティ標準です。
[PCI.S3.1] S3 バケットはパブリック書き込みアクセスを禁止する必要があります
[PCI.S3.1] S3 buckets should prohibit public write access
重大度:重大
以下の指摘と同様です。
- AWS Foundational Security Best Practices
[S3.3] S3 バケットはパブリック書き込みアクセスを禁止する必要があります
[PCI.S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります
[PCI.S3.2] S3 buckets should prohibit public read access
重大度:重大
以下の指摘と同様です。
- AWS Foundational Security Best Practices
[S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります
[PCI.S3.3] S3 バケットでクロスリージョンレプリケーションを有効にする必要があります
[PCI.S3.3] S3 buckets should have cross-region replication enabled
重大度:低
この指摘を駆逐するには、S3 バケットのクロスリージョンレプリケーションを有効にします。
なお、レプリケーションを有効にするには、予めレプリケート元とレプリケート先の両方のバケットで、バージョニングを有効にしておく必要があります。
CloudFormation
クロスリージョンレプリケーションを設定するにあたり、レプリケーション用の IAM Role が必要になります。
クロスリージョンレプリケーションの設定は ReplicationConfiguration プロパティで設定します。
ReplicationPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowSourceBucketAccess
Effect: Allow
Action:
- s3:GetReplicationConfiguration
- s3:ListBucket
Resource:
- !Sub arn:aws:s3:::${BucketName}
- Sid: AllowSourceObjectAccess
Effect: Allow
Action:
- s3:GetObjectVersionForReplication
- s3:GetObjectVersionAcl
- s3:GetObjectVersionTagging
Resource:
- !Sub arn:aws:s3:::${BucketName}/*
- Sid: AllowDestinationObjectAccess
Effect: Allow
Action:
- s3:ReplicateObject
- s3:ReplicateDelete
- s3:ReplicateTags
Resource:
- !Sub arn:aws:s3:::${ReplicationBucketName}/*
ReplicationRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- s3.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- !Ref ReplicationPolicy
Bucket:
Type: AWS::S3::Bucket
Properties:
ReplicationConfiguration:
Role: !GetAtt ReplicationRole.Arn
Rules:
- Status: Enabled
Destination:
Bucket: !Sub arn:aws:s3:::${ReplicationBucketName}
- BucketName はパラメータです。作成するバケット名を指定します。
- ReplicationBucketName はパラメータです。レプリケーション先のバケット名を指定します。
ここではクロスリージョンレプリケーションを実現する上で最低限の設定を掲載しています。ReplicationConfigurationプロパティの設定は多岐に渡りますので、ユースケースに応じて適宜設定を見直してください。
参考
[PCI.S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります
[PCI.S3.4] S3 buckets should have server-side encryption enabled
重大度:中
以下の指摘と同様です。
- AWS Foundational Security Best Practices
[S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります
[PCI.S3.5] S3 バケットは、Secure Socket Layer を使用するリクエストを要求する必要があります
[PCI.S3.5] S3 buckets should require requests to use Secure Socket Layer
重大度:中
以下の指摘と同様です。
- AWS Foundational Security Best Practices
[S3.5] S3 バケットは、Secure Socket Layer を使用するためのリクエストが必要です
[PCI.S3.6] S3 ブロックパブリックアクセス設定を有効にする必要があります
[PCI.S3.6] S3 Block Public Access setting should be enabled
重大度:中
以下の指摘と同様です。
- AWS Foundational Security Best Practices
[S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります
Security Hub 指摘以外でやるべき設定
ここからは Security Hub では指摘されませんが、やっておくことを推奨する設定を紹介します。
ACL無効化
ACL (Access Control List) の無効化は AWS re:Invent 2021 で発表された機能です。
AWS も無効化を推奨しています。
CloudFormation
OwnershipControls プロパティで設定します。
ObjectOwnership の値に BucketOwnerEnforced を設定することにより、ACL が無効化されます。
Bucket:
Type: AWS::S3::Bucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
参考
バージョニング
S3 バケットのバージョニングを有効にすると、オブジェクトを誤って削除したり上書きしてしまっても、復元することができます。
ただし、複数のバージョンを保持する分、ストレージコストは増加するので、その点は理解した上で使用しましょう。
CloudFormation
VersioningConfiguration プロパティで設定します。
Bucket:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
参考
S3 のセキュリティベストプラクティス
ベストプラクティスは読んでおきましょう。
CloudFormation を捧げよ!
ここまで解説してきた内容をすべて含めた CloudFormation テンプレートがこちらです。
必ずしも、すべての設定が必要とは限らないので、ユースケースに応じて適宜見直してください。
#===============================================================================
# CloudFormation Template
#===============================================================================
AWSTemplateFormatVersion: "2010-09-09"
Description: Secure S3 Bucket
#===============================================================================
# Metadata
#===============================================================================
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Parameters
Parameters:
- BucketName
- LoggingBucketName
- ReplicationBucketName
- EncryptionKeyId
#===============================================================================
# Parameters
#===============================================================================
Parameters:
BucketName:
Type: String
LoggingBucketName:
Type: String
ReplicationBucketName:
Type: String
EncryptionKeyId:
Type: String
#===============================================================================
# Resources
#===============================================================================
Resources:
#-----------------------------------------------------------
# S3
#-----------------------------------------------------------
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID: !Ref EncryptionKeyId
BucketKeyEnabled: true
LoggingConfiguration:
DestinationBucketName: !Ref LoggingBucketName
LogFilePrefix: !Ref BucketName
VersioningConfiguration:
Status: Enabled
ReplicationConfiguration:
Role: !GetAtt ReplicationRole.Arn
Rules:
- Status: Enabled
Destination:
Bucket: !Sub arn:aws:s3:::${ReplicationBucketName}
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: DenyInsecureRequests
Effect: Deny
Principal: "*"
Action:
- s3:*
Resource:
- !Sub arn:aws:s3:::${Bucket}
- !Sub arn:aws:s3:::${Bucket}/*
Condition:
Bool:
aws:SecureTransport: false
- Sid: DenySensitiveActionsFromOtherAccounts
Effect: Deny
NotPrincipal:
AWS: !Ref AWS::AccountId
Action:
- s3:DeleteBucketPolicy
- s3:PutBucketAcl
- s3:PutBucketPolicy
- s3:PutEncryptionConfiguration
- s3:PutObjectAcl
Resource:
- !Sub arn:aws:s3:::${Bucket}
- !Sub arn:aws:s3:::${Bucket}/*
#===============================================================================
# Outputs
#===============================================================================
Outputs:
BucketName:
Value: !Ref Bucket
BucketArn:
Value: !GetAtt Bucket.Arn
CLI を捧げよ!
CLI 版はこちらをご参照ください。
↓ ↓ ↓
あとがき
最後まで読んでいただき、ありがとうございます。
本記事によって一匹でも多くの Security Hub 指摘を駆逐できれば幸いです。
本記事が好評でしたら、S3 以外の続編も書いていこうと思います。