Amazon GuardDutyの導入と誤検知対策

# はじめに

JAWS-UG名古屋でAWS上のネットワーク型IDSとしてAmazon GuardDutyを導入している話をしたところ、誤検知対策について興味があるというフィードバックを頂いたので導入方法とともに簡単にまとめてみました。

# 導入方法

+ 単一リージョンに設置するだけならAWS CloudFormationから以下で紹介するスタックテンプレートを使ってスタックを作成すれば有効になります。
+ クラスメソッドさんが[StackSetsを使って全リージョンに展開するやり方](https://dev.classmethod.jp/cloud/aws/set-guardduty-all-region/)を公開されていたので、それに若干手を加えたものを使用しています。
    + 手を加えた点
        + SNS TopicPolicyを設定
            + オリジナルではsns:Publishが許可されていないのでCloudWatch EventsからSNSを叩けません。
        + CloudWatch Eventsのターゲットをカスタマイズ
            + デフォルトの通知では発生した事象を追いにくかったので、どのリソースでどういう事象が起きたのかを最低限拾えるようにInput Transformerで整形しています。
            + Findings(検出した脅威)を調査する際、GuardDutyのコンソールからActionとTargetを見ているでこの2つも出せると楽になりますが、現状そこまで手を入れられていません。
    + 余談
        + SNS TopicPolicyの件はクラスメソッドさんの記事にフィードバックしたつもりでいましたが、Disqusでの投稿がスパム扱いになってフィードバックできてないかも。

```yaml
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  EmailAddress:
    Description: Enter email address to send notification.
    Type: String
Resources:
  GuardDutyDetector:
    Type: 'AWS::GuardDuty::Detector'
    Properties:
      Enable: true
  GuardDutySNSTopic:
    Type: 'AWS::SNS::Topic'
    Properties:
      TopicName: GuardDutyTopic
      Subscription:
      - Endpoint: !Ref EmailAddress
        Protocol: email
  GuardDutySNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: GuardDuty-Topic-Policy
        Version: '2012-10-17'
        Statement:
        - Sid: GuardDuty-Statement
          Effect: Allow
          Principal:
            Service: events.amazonaws.com
          Action: sns:Publish
          Resource: !Ref GuardDutySNSTopic
      Topics: 
      - !Ref GuardDutySNSTopic
  GuardDutyEvent:
    Type: 'AWS::Events::Rule'
    Properties:
      Name: AlertGuardDutyFindings
      Description: 'Alert to SNS topic when find threats by GuardDuty'
      EventPattern: {
                      "source": [
                        "aws.guardduty"
                      ],
                      "detail-type": [
                        "GuardDuty Finding"
                      ]
                    }
      Targets:
        - Arn: !Ref GuardDutySNSTopic
          Id: GuardDutyEventTarget
          InputTransformer:
            InputPathsMap:
                "severity": "$.detail.severity"
                "description": "$.detail.description"
                "region": "$.region"
                "title": "$.detail.title"
                "type": "$.detail.type"
                "account": "$.account"
            InputTemplate: "\"Title: <title>\"\n\"Description: <description>\"\n\"Finding Type: <type>\"\n\"Severity: <severity>\"\n\"Account: <account>\"\n\"Region: <region>\""
```

# 誤検知対策

## Severity(脅威の重大度)によるフィルタリング

+ Severityの低いFindingsは発生頻度も高いので、Severityが高いFindingsを見落とさないようにCloudWatch Eventsでフィルタリングをかけます。
    + [Severityの定義](https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity)
+ 設定には以下のCLIを使用しています。
    + 上述のスタックテンプレートを使用しなかった(できなかった)のは、CloudFormationを使ってEventPatternを設定するとSeverityのフィルタに使用している数値部分が文字列として展開されてしまうためです。
    + EventPatternは>=4のような範囲指定ができないので、Medium以上(Severity>=4)の数値を配列として定義します。

```shell-session
$ aws --region=ap-northeast-1 events put-rule --name AlertGuardDutyFindings --event-pattern "{\"source\":[\"aws.guardduty\"],\"detail-type\":[\"GuardDuty Finding\"],\"detail\":{\"severity\":[4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5.0,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6.0,6.1,6.2,6.3,6.4,6.5,6.6,6.7,6.8,6.9,7.0,7.1,7.2,7.3,7.4,7.5,7.6,7.7,7.8,7.9,8.0,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9,4,5,6,7,8]}}"
```

## 環境ごとの通知方法見直し

+ 開発環境として使用しているVPCを監視対象に含めると、低頻度なオペレーションを脅威として検出する場合があります。
    + GitHub上のシェルスクリプトを実行
        + 実際の攻撃手法として使われる場合があるので検出されるべき
    + Railsの検証で3000番ポート以外(3001番ポートなど)を使用してHTTPアクセス
        + 通常と異なるポートでHTTP通信を検出したため、検出されるべき
+ 開発環境用途なので、機微なデータを扱っていないことを踏まえるとアラートとして通知する必要はない。
    + 通知レベルをワーニングに落としてもいいかも。

# 導入にあたって気をつけること

+ VPC Flow Logs, AWS CloudTrail, DNSログを有効にしてください。
    + GuardDutyを有効にしても分析するイベントがなければ意味がありません。
+ GuardDutyの見方を他のエンジニアに伝えましょう。
    + 基本的にはGuardDutyコンソールのActionとTargetを見れば何が起きたかわかるハズです。
        + 通信方向(Inbound/Outbound)、通信先ホスト、プロトコルなど
    + より詳細に追う場合は、分析元のログをAmazon Athenaに取り込んで手動で分析します。
    + あとは普段やらないことを対象インスタンスでやっていないか、運用者にヒアリングするのが手っ取り早いこともあります。

# 最後に

+ まだ”一応使えている”段階なので、「こうするといいよ！」とか、「こういうときどうしている？」とかフィードバックもらえると嬉しいです。
+ 比較的かんたんに導入できて、(ログとイベント数によりますが)費用的にも安いのでまだやっていないという方はぜひ試してみてください。
    + ちなみにAmazon GuardDutyははじめの30日は無料で使用でき、コンソールからその間の目安金額を確認することができます。