GuardDutyは、AWSアカウントのイベントやネットワークトラフィックを監視して、不正アクセス、データ漏洩、マルウェアの兆候など不審な動作や脅威を自動的に検出するセキュリティサービス。検出結果とサマリーをGuardDutyコンソールに可視化してくれる。
具体的には次のような不審な動きを検出してくれる(と、AWS営業さんが熱心に語っていた)
- ブルートフォース攻撃
- 通常アクセスされない地域やIPからの接続試行
- S3から外部への大規模データ転送
- EC2の削除、IAM権限の変更
- EC2がボットネットのC2サーバーと通信
- EC2から外部への異常なトラフィック(例: マルウェアのダウンロード)
- 高頻度でスキャンを行うポートスキャン
- VPCから外部IPへの大量のデータ送信
- ブラックリスト登録済みのIPアドレスとの通信
- 既知のマルウェア感染ホストへの接続
データソースにはAWS CloudTrail、Amazon VPC フローログ、DNS ログをデータソースとして利用する。
Amazon GuardDuty は、AWS CloudTrail、VPC フローログ、AWS DNS ログから独立したデータストリームを直接取得します。Amazon S3 バケットポリシーを管理したり、ログを収集して保存する方法を変更したりする必要はありません。
Amazon GuardDutyを導入する前に知っておきたいこと | DevelopersIO
GuardDutyの有効化
GuardDutyを有効化するだけで、独立したデータストリームからAWS CloudTrail、Amazon VPC フローログ、DNS ログ
を継続的にモニタリングしてくれる。
検出の通知
脅威を検出すると、==FindingをGuardDutyのコンソールにリストアップしてくれるが、SNS通知はCloudWatch Eventsで自力で構成する必要がある。
GuardDutyでFindingが発生すると、CloudWatch Eventsルールが発火します。
Amazon GuardDutyを導入する前に知っておきたいこと | DevelopersIO
Amazon EventBridge
EventBridgeでGuardDutyの脅威検出のイベントGuardDuty Findingに対して、SNSに連携するためのルールを作成する
イベントパターン
フックするイベントを定義する which
デフォルトのイベントパターン
イベントパターンについては、デフォルトの記載のままだと、検知したすべてを通知することになります。以下はすべての検知を通知する例です。
【AWS】GuardDutyでイベント検知したらメール通知する仕組みを作る|hiroyu0510
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"]
}
脅威にはかなりのパターンがあるので、SNS通知は緊急度の高い脅威レベル(=severity)でフィルタリングして、定常的にGuardDutyコンソールを保守する運用でいく。
もし、通知をフィルタリングしたい場合、危険度Midium以上とか危険度HIGH以上に限定して通知するというような場合は、以下のようにすることもできます。例ですが、危険度4以上(Midium以上)の場合に通知する設定です。severityでフィルタリングをかけることができます。
【AWS】GuardDutyでイベント検知したらメール通知する仕組みを作る|hiroyu0510
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [{
"numeric": [">=", 4]
}]
}
}
ターゲット(SNS)への入力
~ルール > 編集 > ターゲットを選択 > ターゲットN > 追加設定 > 入力を設定 > ターゲット入力を設定~から 入力トランスフォーマーを選択することで、ターゲットへの入力データをカスタマイズできる
入力パス what
使用したいGuardDuty FindingイベントのデータをJSONオブジェクトの任意キーにマッピングする
~付録 > GuardDutyのサンプルイベント~
{
"Account_ID": "$.detail.accountId",
"Finding_ID": "$.detail.id",
"Finding_Type": "$.detail.type",
"Finding_description": "$.detail.description",
"eventFirstSeen": "$.detail.service.eventFirstSeen",
"region": "$.region",
"severity": "$.detail.severity"
}
テンプレート how
入力パスに定義したデータキーを使って、ターゲットに渡すテンプレートを作成する
テキストでもjsonでも良い
"重要度 <severity> のGuardDutyイベントが発生しました。"
"アカウントID: <Account_ID>"
"発生日時: <eventFirstSeen>"
"検出タイプ: <Finding_Type>"
"リージョン: <region>"
"タイプの説明: <Finding_description>"
"レポートURL: https://<region>.console.aws.amazon.com/guardduty/home?region=<region>#/findings?macros=current&fId=<Finding_ID>"
出力例 result
"重要度 5 のGuardDutyイベントが発生しました。"
"アカウントID: 123456789012"
"発生日時: 2017-10-31T23:16:23Z"
"検出タイプ: Canary:EC2/Stateless.IntegTest"
"リージョン: us-east-1"
"タイプの説明: Canary:EC2/Stateless.IntegTest"
"詳細はGuardDuty コンソール( https://us-east-1.console.aws.amazon.com/guardduty/home?region=us-east-1#/findings?macros=current&fId=16afba5c5c43e07c9e3e5e2e544e95df )を確認してください。
入力パス、テンプレート、および出力の例
動作確認
GuardDutyに対して、Backdoorテストイベントを発火してSNSトピックのサブスクライバーに届いたら完了
detector-idはアカウント/リージョン固有に割り当てられたGuardDutyのuuidで、GuardDuty > 設定から確認可能
aws guardduty create-sample-findings \
--detector-id 9XcXaXcX2XdX0X4XeX8XaX8XaX7X3X4X \
--finding-types "Backdoor:EC2/DenialOfService.Dns"
脅威に対する公式シューティングガイド
脅威のシューティングはAWS公式ガイドを参考に対策する
GuardDuty 検出結果タイプ - Amazon GuardDuty
マルウェアスキャン
[神アップデート]GuardDutyがEC2やECSのマルウェア検知時のスキャンに対応したので実際にスキャンさせてみた #reinforce | DevelopersIO
- Backdoor:EC2/C&CActivity.BやCryptoCurrency:EC2/BitcoinTool.B!DNSなどマルウェアの動作が疑われるFindings検知があると自動でマルウェアスキャンがトリガーされる。
- オンデマンドのマルウェアスキャンもある
付録
GuardDutyのイベントサンプル
{
"version": "0",
"id": "c8c4daa7-a20c-2f03-0070-b7393dd542ad",
"detail-type": "GuardDuty Finding",
"source": "aws.guardduty",
"account": "123456789012",
"time": "1970-01-01T00:00:00Z",
"region": "us-east-1",
"resources": [],
"detail": {
"schemaVersion": "2.0",
"accountId": "123456789012",
"region": "us-east-1",
"partition": "aws",
"id": "16afba5c5c43e07c9e3e5e2e544e95df",
"arn": "arn:aws:guardduty:us-east-1:123456789012:detector/123456789012/finding/16afba5c5c43e07c9e3e5e2e544e95df",
"type": "Canary:EC2/Stateless.IntegTest",
"resource": {
"resourceType": "Instance",
"instanceDetails": {
"instanceId": "i-05746eb48123455e0",
"instanceType": "t2.micro",
"launchTime": 1492735675000,
"productCodes": [],
"networkInterfaces": [{
"ipv6Addresses": [],
"privateDnsName": "ip-0-0-0-0.us-east-1.compute.internal",
"privateIpAddress": "0.0.0.0",
"privateIpAddresses": [{
"privateDnsName": "ip-0-0-0-0.us-east-1.compute.internal",
"privateIpAddress": "0.0.0.0"
}],
"subnetId": "subnet-d58b7123",
"vpcId": "vpc-34865123",
"securityGroups": [{
"groupName": "launch-wizard-1",
"groupId": "sg-9918a123"
}],
"publicDnsName": "ec2-11-111-111-1.us-east-1.compute.amazonaws.com",
"publicIp": "11.111.111.1"
}],
"tags": [{
"key": "Name",
"value": "ssh-22-open"
}],
"instanceState": "running",
"availabilityZone": "us-east-1b",
"imageId": "ami-4836a123",
"imageDescription": "Amazon Linux AMI 2017.03.0.20170417 x86_64 HVM GP2"
}
},
"service": {
"serviceName": "guardduty",
"detectorId": "3caf4e0aaa46ce4ccbcef949a8785353",
"action": {
"actionType": "NETWORK_CONNECTION",
"networkConnectionAction": {
"connectionDirection": "OUTBOUND",
"remoteIpDetails": {
"ipAddressV4": "0.0.0.0",
"organization": {
"asn": -1,
"isp": "GeneratedFindingISP",
"org": "GeneratedFindingORG"
},
"country": {
"countryName": "United States"
},
"city": {
"cityName": "GeneratedFindingCityName"
},
"geoLocation": {
"lat": 0,
"lon": 0
}
},
"remotePortDetails": {
"port": 22,
"portName": "SSH"
},
"localPortDetails": {
"port": 2000,
"portName": "Unknown"
},
"protocol": "TCP",
"blocked": false
}
},
"resourceRole": "TARGET",
"additionalInfo": {
"unusualProtocol": "UDP",
"threatListName": "GeneratedFindingCustomerListName",
"unusual": 22
},
"eventFirstSeen": "2017-10-31T23:16:23Z",
"eventLastSeen": "2017-10-31T23:16:23Z",
"archived": false,
"count": 1
},
"severity": 5,
"createdAt": "2017-10-31T23:16:23.824Z",
"updatedAt": "2017-10-31T23:16:23.824Z",
"title": "Canary:EC2/Stateless.IntegTest",
"description": "Canary:EC2/Stateless.IntegTest"
}
}