AWS GuardDutyで実現するVPC内通信の包括的脅威検知
目的
• VPC内通信の不正アクセスをリアルタイムで検知
セキュリティパイプラインの現状
No. | サービス | 目的 |
---|---|---|
1 | Amazon GuardDuty | 脅威検知(VPC Flow Logs + 脅威インテリジェンス) |
2 | EventBridge | アラート通知(Slack連携) |
3 | Amazon Detective | インシデント調査・フォレンジック |
4 | Security Lake | 長期保存・相関分析 |
VPC Flow Logsの監視対象通信
1. 内部通信
• 同一/異なるサブネット間のEC2通信
• すべてのプロトコル(TCP/UDP/ICMP等)のプライベートIP間通信
2. 外部通信
• Internet Gateway経由の通信
• NAT Gateway経由のインターネットアクセス
• Elastic IP宛の着信通信
3. AWS サービス連携
• VPCエンドポイント(Interface/Gateway)経由の通信
• ロードバランサー関連トラフィック
• マネージドサービス(Lambda/EKS/RDS等)のENI通信
4. ハイブリッド接続
• VPN/Direct Connect経由のオンプレミス通信
• VPCピアリングによるVPC間通信
• Transit Gateway経由の通信
GuardDuty中心の検知アーキテクチャ
データソースと検知内容
データソース | 主な検知内容 | 特徴 |
---|---|---|
VPC Flow Logs | ・不審な外部通信 ・ポートスキャン ・異常な通信パターン |
ネットワークレベルの脅威検知 |
CloudTrail | ・権限昇格 ・設定変更 ・異常なAPI呼び出し |
管理アクションの監視 |
DNS クエリ | ・C2通信 ・DNSトンネリング ・DGAドメインアクセス |
マルウェア活動の早期発見 |
EKS 監査ログ | ・コンテナ環境の異常 ・権限昇格 ・不正アクセス |
コンテナセキュリティ |
追加検討オプション
Malware Protection for S3
- コスト目安(1TBのS3バケットの場合):
- 初回フルスキャン:約¥1,024(一回限り)
- 月間運用コスト:
- 低更新率(5%/月):約¥51/月
- 中更新率(10%/月):約¥102/月
- 高更新率(20%/月):約¥205/月
- 年間運用コスト:
- 低更新率:約¥612/年
- 中更新率:約¥1,224/年
- 高更新率:約¥2,460/年
検知から対応までのフロー
- GuardDutyによる自動検知
- EventBridgeによるSlack通知
- Detectiveを用いた原因調査
- 必要に応じた対応アクション実行
主な検知シナリオ
• 不正アクセス:ブルートフォース攻撃、権限昇格
• データ漏洩:異常な大量データ転送、不審な外部通信
• マルウェア活動:C2通信、暗号通貨マイニング
• 設定ミス悪用:過剰な権限、公開設定の悪用
GuardDutyセキュリティ監視システムの要件
1. 基本的な監視要件
• GuardDuty検出器を有効化し、セキュリティ脅威の検出を行う
• 検出結果の公開頻度を6時間ごとに設定
• すべての重要度の検出結果を監視対象とする
2. データソース監視要件
• S3ログの監視を有効化
• EC2インスタンスのマルウェア保護(EBSボリュームスキャン)を有効化
3. 通知要件
• GuardDutyの検出結果をSNSトピック「guardduty-finding」に送信
• 検出結果をメールアドレス「xxxxx@xxxxx.com」に通知
• Slack通知の準備
4. イベント検知要件
• GuardDutyのすべての検出結果を検知するEventBridgeルールを設定
• GuardDuty検出結果のアーカイブ操作(ArchiveFindings、UpdateFindingsFeedback)も検知
5. 権限要件
• EventBridgeからSNSトピックへの発行権限を持つIAMロールを設定
• 適切な権限分離とセキュリティポリシーの適用
6. 運用要件
• 検出結果の管理(アーカイブ操作の追跡)
• 検出結果の通知システムの構築
• セキュリティイベントへの迅速な対応体制の整備
シーケンス図
Terraform設計
main.tf
# GuardDuty検出器の設定
resource "aws_guardduty_detector" "xxxxx" {
enable = true
finding_publishing_frequency = "SIX_HOURS"
datasources {
kubernetes {
audit_logs {
enable = false
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
enable = true
}
}
}
s3_logs {
enable = true
}
}
}
# EventBridgeからSNSへの権限を持つIAMロール
resource "aws_iam_role" "eventbridge_to_sns" {
name = "eventbridge_to_sns"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Principal = { Service = "events.amazonaws.com" },
Action = "sts:AssumeRole"
}]
})
}
# SNSトピックへの発行権限を定義するポリシードキュメント
data "aws_iam_policy_document" "publish_sns" {
statement {
sid = "AllowPublishToGuarddutyFindingTopic"
effect = "Allow"
actions = [
"sns:Publish"
]
resources = [
"arn:aws:sns:ap-northeast-1:${data.aws_caller_identity.current.account_id}:guardduty-finding"
]
}
}
# SNS発行権限のIAMポリシー
resource "aws_iam_policy" "publish_sns" {
name = "EventBridgePublishGuarddutyFinding"
policy = data.aws_iam_policy_document.publish_sns.json
}
# IAMポリシーをロールにアタッチ
resource "aws_iam_policy_attachment" "attach" {
name = "attach-eb-sns"
roles = [aws_iam_role.eventbridge_to_sns.name]
policy_arn = aws_iam_policy.publish_sns.arn
}
# GuardDuty検出結果通知用SNSトピック
resource "aws_sns_topic" "guardduty_finding" {
name = "guardduty-finding"
display_name = "put-slack"
fifo_topic = false
tags = {
Name = "guardduty-finding"
}
}
# SNSトピックのメール通知設定
resource "aws_sns_topic_subscription" "email" {
endpoint = "xxxxx@xxxxx.com"
protocol = "email"
topic_arn = aws_sns_topic.guardduty_finding.arn
confirmation_timeout_in_minutes = 1
endpoint_auto_confirms = false
raw_message_delivery = false
}
# GuardDutyアーカイブAPI呼び出しを検知するルール
resource "aws_cloudwatch_event_rule" "gdu_finding_archive_api" {
name = "gdu-finding-archive-api"
description = "Notify when a GuardDuty finding is archived (API call)"
event_bus_name = "default"
state = "ENABLED"
event_pattern = jsonencode({
source = ["aws.guardduty"]
detail-type = ["AWS API Call via CloudTrail"]
detail = {
eventSource = ["guardduty.amazonaws.com"]
eventName = ["ArchiveFindings", "UpdateFindingsFeedback"]
}
})
}
# GuardDutyの全検出結果を受け取るルール
resource "aws_cloudwatch_event_rule" "guardduty_finding" {
name = "guardduty-finding"
description = "GuardDutyのすべての検出結果(全重要度)をSNSトピックに送信"
event_bus_name = "default"
state = "ENABLED"
event_pattern = jsonencode({
source = ["aws.guardduty"]
detail-type = ["GuardDuty Finding"]
})
}
# アーカイブ検知をSNSトピックに送るターゲット
resource "aws_cloudwatch_event_target" "guardduty_archive_to_sns" {
rule = aws_cloudwatch_event_rule.gdu_finding_archive_api.name
target_id = "guardduty-archive-notification"
arn = "arn:aws:sns:ap-northeast-1:${data.aws_caller_identity.current.account_id}:guardduty-finding"
role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/eventbridge_to_sns"
}
# 全検出結果をSNSトピックに送るターゲット
resource "aws_cloudwatch_event_target" "guardduty_finding" {
rule = aws_cloudwatch_event_rule.guardduty_finding.name
target_id = "guardduty-finding"
arn = "arn:aws:sns:ap-northeast-1:${data.aws_caller_identity.current.account_id}:guardduty-finding"
role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/eventbridge_to_sns"
}
Discussion