GuardDutyでセキュリティリスクを可視化する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/9362fc28-852c-1965-b839-f63b00223139.png" alt="aws" width="80">

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](https://dev.classmethod.jp/articles/amazon-guardduty-first/)

## GuardDutyの有効化
GuardDutyを有効化するだけで、独立したデータストリームから`AWS CloudTrail、Amazon VPC フローログ、DNS ログ`を継続的にモニタリングしてくれる。

## 検出の通知

脅威を検出すると、=**=Finding**をGuardDutyのコンソールにリストアップしてくれるが、SNS通知はCloudWatch Eventsで自力で構成する必要がある。

> GuardDutyでFindingが発生すると、CloudWatch Eventsルールが発火します。
> [Amazon GuardDutyを導入する前に知っておきたいこと | DevelopersIO](https://dev.classmethod.jp/articles/amazon-guardduty-first/)

### Amazon EventBridge

EventBridgeでGuardDutyの脅威検出のイベント**GuardDuty Finding**に対して、SNSに連携するためのルールを作成する

#### イベントパターン 

**フックするイベントを定義する which**

**デフォルトのイベントパターン**

> イベントパターンについては、デフォルトの記載のままだと、検知したすべてを通知することになります。以下はすべての検知を通知する例です。
> [【AWS】GuardDutyでイベント検知したらメール通知する仕組みを作る｜hiroyu0510](https://note.com/hiroyu0510/n/n40ceb8a55a00)

```json:フックするイベントパターン=デフォルト全て
{
  "source": ["aws.guardduty"],
  "detail-type": ["GuardDuty Finding"]
}
```

脅威にはかなりのパターンがあるので、SNS通知は緊急度の高い脅威レベル(=severity)でフィルタリングして、定常的にGuardDutyコンソールを保守する運用でいく。

> もし、通知をフィルタリングしたい場合、危険度Midium以上とか危険度HIGH以上に限定して通知するというような場合は、以下のようにすることもできます。例ですが、危険度4以上(Midium以上)の場合に通知する設定です。severityでフィルタリングをかけることができます。
> [【AWS】GuardDutyでイベント検知したらメール通知する仕組みを作る｜hiroyu0510](https://note.com/hiroyu0510/n/n40ceb8a55a00)

```json:フックするイベントパターンを重要度レベル4(Medium)以上にフィルタする
{
  "source": ["aws.guardduty"],
  "detail-type": ["GuardDuty Finding"],
  "detail": {
    "severity": [{
      "numeric": [">=", 4]
    }]
  }
}
```

#### ターゲット(SNS)への入力

~ルール > 編集 > ターゲットを選択 > ターゲットN > 追加設定 > 入力を設定 > ターゲット入力を設定~から **入力トランスフォーマー**を選択することで、ターゲットへの入力データをカスタマイズできる

**入力パス what**

使用したいGuardDuty FindingイベントのデータをJSONオブジェクトの任意キーにマッピングする
~付録 > GuardDutyのサンプルイベント~ 

```json:入力パス
{
    "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でも良い

```text:テンプレート
"重要度 <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**

```text:テンプレート整形後にSNSに送られるデータ
"重要度 5 のGuardDutyイベントが発生しました。"
"アカウントID： 123456789012"
"発生日時： 2017-10-31T23:16:23Z" 
"検出タイプ： Canary:EC2/Stateless.IntegTest"
"リージョン： us-east-1"
"タイプの説明： Canary:EC2/Stateless.IntegTest"
"レポートURL: https://us-east-1.console.aws.amazon.com/guardduty/home?region=us-east-1#/findings?macros=current&fId=16afba5c5c43e07c9e3e5e2e544e95df ）"
```

**入力パス、テンプレート、および出力の例**

![image 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417736/d86db1a0-d530-a5ad-b06a-0daa04fbee88.png)

#### 動作確認

GuardDutyに対して、Backdoorテストイベントを発火してSNSトピックのサブスクライバーに届いたら完了

detector-idはアカウント/リージョン固有に割り当てられたGuardDutyのuuidで、GuardDuty > 設定から確認可能

```sh:sh
aws guardduty create-sample-findings \
  --detector-id 9XcXaXcX2XdX0X4XeX8XaX8XaX7X3X4X \
  --finding-types "Backdoor:EC2/DenialOfService.Dns"
```

## 脅威に対する公式シューティングガイド
脅威のシューティングはAWS公式ガイドを参考に対策する
[GuardDuty 検出結果タイプ - Amazon GuardDuty](https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_finding-types-active.html)

## マルウェアスキャン
[\[神アップデート\]GuardDutyがEC2やECSのマルウェア検知時のスキャンに対応したので実際にスキャンさせてみた \#reinforce | DevelopersIO](https://dev.classmethod.jp/articles/guardduty-support-malware-protection/)

- **Backdoor:EC2/C&CActivity.B**や**CryptoCurrency:EC2/BitcoinTool.B!DNS**などマルウェアの動作が疑われるFindings検知があると自動でマルウェアスキャンがトリガーされる。
- オンデマンドのマルウェアスキャンもある

## 付録

### GuardDutyのイベントサンプル

```json:json
{
  "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"
  }
}
```