はじめに
この記事はセキュリティチームの Sysdig 活用事例をテーマにした「Sysdigブログリレー」8 日目の記事です。
今回は、AWS 環境を CSPM でチェックした際に検知されるような項目と、その対応例をいくつかご紹介します。
CSPM でチェックした環境
今回の記事用に、下記のような構成を検証用の AWS 環境に Terraform で準備し、Sysdig CSPM でチェックしました。
最低限の Web サーバーを想定した構成で、HTML ファイルを提供する EC2 サーバーと、画像を提供する S3 Bucket から構成されています。
このような環境で、どのようなリスクが検出されるか、確認したいと思います。
Sysdig の CSPM では様々なコンプライアンスポリシーが選択できますが、今回は「CIS Amazon Web Services Foundations Benchmark」を利用しました。
CIS Bentchmark は複数のクラウドプロバイダーに対応し、Kubernetes などに対応した Benchmark もあることから、汎用的に使いやすいため選定しました。
「CIS Amazon Web Services Foundations Benchmark」については Sysdig ブログリレー 6 日目の「CIS AWS Benchmark の モニタリング要件は GuardDuty + Sysdig でどこまでカバーできるのか?」をご参照ください。
検知された項目と対応例
リソースの状況と運用を照らし合わせ、リスク対応を行います。
リスク対応は ISO 31000 でその手法が定められており、環境に合わせて対策を行います。
リスク許容を選択する際の対応方法については Sysdig ブログリレー 1 日目の「Sysdig CSPMで検出された項目に対応する」をご参照ください。
それでは、検知された項目と、実際に対応した内容を一部ご紹介します。
2.1.1 Ensure S3 Bucket Policy is set to deny HTTP requests
このポリシーでは、S3バケットへのリクエストをHTTPS 経由のみに制限することが推奨されています。
今回の環境では、CloudFrontからのアクセスを許可するバケットポリシーを設定しています。
resource "aws_s3_bucket" "image" { bucket = "${var.project_name}-${var.env}-images" } resource "aws_s3_bucket_policy" "image" { bucket = aws_s3_bucket.image.id policy = data.aws_iam_policy_document.static.json } data "aws_iam_policy_document" "static" { statement { sid = "Allow CloudFront" effect = "Allow" principals { type = "Service" identifiers = ["cloudfront.amazonaws.com"] } actions = [ "s3:GetObject" ] resources = [ "${aws_s3_bucket.image.arn}/*" ] condition { test = "StringEquals" variable = "aws:SourceArn" values = [aws_cloudfront_distribution.distribution.arn] } } }
ポリシーに準拠するには、HTTP リクエストを明示的に拒否する設定をバケットポリシーに入れる必要があります。
Sysdig では下記のように対応例が表示されますので、これを参考に HTTP リクエストを明示的に拒否する設定をバケットポリシーに入れます。
Terraform で対応する場合、下記のようなコードを追加することで設定します。
data "aws_iam_policy_document" "static" { # ... statement { sid = "SSLRequestsOnly" effect = "Deny" principals { type = "*" identifiers = ["*"] } actions = [ "s3:*" ] resources = [ "${aws_s3_bucket.image.arn}", "${aws_s3_bucket.image.arn}/*" ] condition { test = "Bool" variable = "aws:SecureTransport" values = ["false"] } } }
このように、そもそもリスクとなっている要因に対応できる場合は、リスク源を除去します。
この対応により、HTTP 通信では接続することができなくなるため、ポリシーに準拠可能です。
2.1.2 Ensure MFA Delete is enabled on S3 buckets
S3 バケットで MFA 削除を有効にすることが推奨されています。
MFA 削除を有効にするには、バージョニングを有効にする必要があります。
特定のバージョンを削除したり、バケットのバージョニング状態を変更したりするリクエストに対して、追加の認証が必要になり、セキュリティが強化されます。
オブジェクトの削除を保護するため、バージョニングを有効にします。
Sysdig では下記のように対応例が表示されますので、これを参考にします。
Terraform で対応する場合は、下記のようなコードを追記します。
resource "aws_s3_bucket_versioning" "image" { bucket = aws_s3_bucket.image.id versioning_configuration { status = "Enabled" } }
今回の環境では、MFA 削除まで有効にすると、オブジェクトバージョンの削除に Root アカウントが必須になるなど運用上の弊害も出るため、Sysdig 側で「S3 – Enabled MFA Delete」のリスク許容の設定を行います。
Sysdig では、一般的にはリソース単位でリスク許容の設定を行いますが、Zone 単位でのリスク許容設定も可能です。
Zone 単位でリスク許容を行う場合は、チェック結果の一覧の画面で、対象の Control の右側に表示されている、「Accept Risk」から設定します。
今回は環境内全てのバケットに対してリスク許容を行うため、Zone 単位で設定しました。
2.1.4 Ensure that S3 Buckets are configured with ‘Block public access (bucket settings)’
このポリシーでは、S3バケットは、ブロックパブリックアクセスを有効にすることが推奨されています。
S3 バケットは、設定により パブリックアクセス (認証を必要としないアクセス) が可能です。
ブロックパブリックアクセスを設定することで、パブリックアクセスを許可するような変更を拒否したり、パブリックアクセス そのものを拒否することが可能となります。
AWS では、 バケット単位、アカウント単位のブロックパブリックアクセスがそれぞれ可能であり、Sysdig では、バケット単位の設定、アカウント単位の設定がそれぞれチェックされます。
今回の環境では、対象のバケットに対してのブロックパブリックアクセスは有効になっていたのですが、アカウント単位の設定のチェックで検知されていました。
アカウント単位でのブロックパブリックアクセスのチェックは下記の箇所を見ているため、この設定を修正します。
Sysdig では下記のように対応例が表示されますので、これを参考にアカウント単位のブロックパブリックアクセスの設定を行います。
アカウント単位での対応を Terraform で修正する場合は下記のコードで対応します。
resource "aws_s3_account_public_access_block" "example" { block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
一部公開する必要があるバケットがある場合は、 アカウント単位の対応をすることができません。
このような場合は、期限なしでリスク許容の設定を行います。
5.1 Ensure no Network ACLs allow ingress from 0.0.0.0/0 to remote server administration ports
ネットワークACLインバウンドエントリがTCPポート 22 または 3389 に対して無制限のアクセスを許可しないことが推奨されています。
構築した VPC での検知
今回の環境では、セキュリティグループで SSH 接続可能な IP を制限していましたが、ネットワーク ACL はデフォルトのまま、全許可されていました。
Sysdig では下記のように対応例が表示されますので、これを参考にネットワーク ACLのインバウンドルールを修正します。
インバウンドルールに、特定の IP からTCPポート 22 へのインバウンド許可のルールを入れました。
また、全てのインバウンドを許可するルールは削除し、Web のポートのみ許可するルールを入れました。
Terraform で構成する場合、下記のようなコードとなります。
resource "aws_default_network_acl" "main" { default_network_acl_id = aws_vpc.vpc.default_network_acl_id # egress all allow egress { protocol = -1 rule_no = 100 action = "allow" cidr_block = "0.0.0.0/0" from_port = 0 to_port = 0 } ingress { protocol = "tcp" rule_no = 100 action = "allow" cidr_block = local.allowed_cidr from_port = 22 to_port = 22 } ingress { protocol = "tcp" rule_no = 200 action = "allow" cidr_block = "0.0.0.0/0" from_port = 80 to_port = 80 } ingress { protocol = "tcp" rule_no = 300 action = "allow" cidr_block = "0.0.0.0/0" from_port = 443 to_port = 443 } }
デフォルト VPC での検知
全リージョンのデフォルト VPC も検知されていました。
今回の環境では、デフォルトVPC は使用する予定がないため、全リージョンで削除を行います。
5.6 Ensure that EC2 Metadata Service only allows IMDSv2
EC2 インスタンスは、IMDSv2 を必須とすることが推奨されています。
IMDSv2 は、メタデータの参照の際にトークンを必須となっているため、Server Side Request Forgery (SSRF) 脆弱性を突いた、メタデータを利用した攻撃を受けにくいです。
OS は Amazon Linux 2 で構築したのですが、デフォルトで IMDSv1 が利用可能となっていました。
IMDSv2 を必須とするよう、変更します。
Sysdig では下記のように対応例が表示されますので、これを参考にEC2インスタンスのIMDSv2 の設定を行います。
Terraform で構成する場合、下記のようなコードをEC2 インスタンスの設定に追記します。
resource "aws_instance" "web" { # ... metadata_options { http_tokens = "required" } }
Amazon Linux 2023 では IMDSv2 必須がデフォルトになっています。
すぐには対応せず、OS のアップデートなどで対応する場合には、Sysdig 側で期間を指定してリスク許容を行います。
おわりに
今回は、一般的な環境を例に、実際に検知された項目への対応方法をご紹介しました。
全ての項目で、現状を確認しながら対応していくのは大変ですが、最初が一番肝心です。
一度綺麗な状態にすると、定期的に検知状況を確認するような運用を行うことで、意図しない設定不備にすぐ気づくことができ、CSPM は真の効果を発揮します。
CSPM を活用し、クラウド環境の設定をチェック・管理を行ってはどうでしょうか。
Sysdig ブログリレーとしては、今日の記事が最後となります。
次回の記事は、振り返りとして「Sysdig ブログリレー 振り返り」を予定しています。
最後までお付き合いください。