AWS Security Hub の検出結果を自動で「通知済み」にする

2022.09.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Security Hub 検知の通知(or 自動起票)の悩み

AWS Security Hub にセキュリティイベントを集約して、 アクションのトリガーを作成するケースは多いです。 「メール・Slackへ通知」するケースもありますし、 「特定タスク管理ツールへ自動起票する」仕組みを作ることもあります。 例えば以下のブログでは、「Security Hub検知をBacklogへ自動起票する仕組み」を作っています。

こういった通知(or 自動起票)の仕組みを作ったときに出てくる悩みとして、 「定期的に同じ通知が飛んでくる」があります。 これはSecurity Hubの定期的なチェックのためです。 チェックを行うたびに検出結果が更新されて、それが検知されます。

最初のチェックの後、各コントロールのスケジュールは、定期的に実行されるか、変更によってトリガーされます。

  • 定期的なチェックは、最後の実行から 12 時間以内に自動的に実行 されます。周期を変更することはできません。
  • 変更によってトリガーされるチェックは、関連付けられたリソースの状態が変更されたときに実行されます。リソースの状態が変わらない場合でも、変更によってトリガーされるチェックの更新時刻は 18 時間ごとに更新 されます。これは、コントロールがまだ有効であることを知るのに便利です。

– 引用: セキュリティチェックの実行スケジュール - AWS Security Hub

ワークフローステータスの活用

同じ通知が飛ばないようにするためには ワークフローのステータス を活用できます。 これは各検出結果に設定できるステータスです。 NEW (新規), NOTIFIED (通知済み) SUPPRESSED (抑制済み), RESOLVED (解決済み) の4値のいずれかを設定できます。

img

例えば通知された検出結果を NOTIFIED (通知済み)に変更したとします。 EventBridgeルールで「 NOTIFIED にしたものは通知対象外にする」フィルタ(参考: 例3)を設定することで、 その通知( NOTIFIED にしたもの ) は再度通知されなくなります。

『「通知済み」にする』を自動化する

今回は「通知された検出結果を NOTIFIED (通知済み)に変更する」部分を 自動化します。Step Functionsを使って簡単に実装できます。

作ったもの

以下リソース(EventBridge, Step Functions)を作りました。

img

EventBridgeルール(フィルタ)

EventBridgeルールのフィルタパターンは以下のようにしました。 CRITICALの検出結果で失敗しているコントロールを検知します。

{
  "detail": {
    "findings": {
      "Compliance": {
        "Status": [{
          "anything-but": "PASSED"
        }]
      },
      "ProductName": ["Security Hub"],
      "RecordState": ["ACTIVE"],
      "Severity": {
        "Label": ["CRITICAL"]
      },
      "Workflow": {
        "Status": ["NEW"]
      }
    }
  },
  "detail-type": ["Security Hub Findings - Imported"],
  "source": ["aws.securityhub"]
}

【注意】ワークフローのステータス(Workflow.Status)のフィルタを必ず付与してください。 このフィルタがないと以下のようなループが発生します。

  1. 検出結果がEventBridge で検知、Step Functionsステートマシンが起動される
  2. 検出結果を「通知済み」に更新する
  3. 更新した検出結果が EventBridge で検知、Step Functionsステートマシンが起動される
  4. 検出結果を「通知済み」に更新する
  5. 更新した検出結果が EventBridge で検知、Step Functionsステートマシンが起動される
  6. 検出結果を「通知済み」に更新する
  7. (以下無限ループ)

EventBridgeルール(ターゲット)

EventBridgeルールのターゲット設定は以下のとおり。Step Functionsステートマシンを指定します。

img

ターゲットにステートマシンを指定するときに、IAMロールが必要になります。 キャプチャの test-security-events-role の部分です。 IAMロールのポリシーは以下のように 「ステートマシンの起動」のみを許可しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "states:StartExecution",
      "Resource": "${aws_sfn_state_machine.this.arn}"
    }
  ]
}

Step Functionsステートマシン

ステートマシンの構成は以下のとおり。見てのとおりシンプルです。

img

BatchUpdateFindings APIを実行しています。 入力パラメータは以下のとおり。

{
  "FindingIdentifiers": [
    {
      "Id.$": "$.detail.findings[0].Id",
      "ProductArn.$": "$.detail.findings[0].ProductArn"
    }
  ],
  "Workflow": {
    "Status": "NOTIFIED"
  }
}

(追記) ステートマシンのIAMロールには以下のように、 securityhub:BatchUpdateFindings アクションを許可する必要があります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "securityhub:BatchUpdateFindings"
      ],
      "Resource": "*"
    }
  ]
}

確認

「SSHを全開放」なEC2セキュリティグループを作成してみます。 これは基礎セキュリティのベストプラクティスの [EC2.19] Security groups should not allow unrestricted access to ports with high risk にて非準拠になります。

img

しばらくして確認すると、すでに NOTIFIED になっていました。

img

ステートマシンの実行ログも確認しました。問題ないですね。

img

おわりに

AWS Security Hub の検出結果を自動で「通知済み」にする仕組みを作ってみました。

実際にはこれ単体で使うことは無いです。 以下のような組み合わせで活用する想定です。

  • このステートマシンに「通知(or 自動起票)の処理」を追加する
  • EventBridgeルールのターゲットに「通知(or 自動起票)の処理」を追加する 等

以上、参考になれば幸いです。

参考

追記情報

【2023-09-15】 ループがそもそも出ないように対策した Step Functions ステートマシン

【注意】ワークフローのステータス(Workflow.Status)のフィルタを必ず付与してください。 このフィルタがないと以下のようなループが発生します。

上記のループ対策版 Step Functions ステートマシンを以下に記載します。

{
  "Comment": "Security Hub finding handler",
  "StartAt": "Choice by workflow status",
  "States": {
    "Choice by workflow status": {
      "Type": "Choice",
      "Choices": [
        {
          "Not": {
            "Variable": "$.detail.findings[0].Workflow.Status",
            "StringEquals": "NOTIFIED"
          },
          "Comment": "not NOTIFIED",
          "Next": "Set a finding as NOTIFIED"
        }
      ],
      "Default": "End"
    },
    "End": {
      "Type": "Pass",
      "End": true
    },
    "Set a finding as NOTIFIED": {
      "Type": "Task",
      "Parameters": {
        "FindingIdentifiers": [
          {
            "Id.$": "$.detail.findings[0].Id",
            "ProductArn.$": "$.detail.findings[0].ProductArn"
          }
        ],
        "Workflow": {
          "Status": "NOTIFIED"
        }
      },
      "Resource": "arn:aws:states:::aws-sdk:securityhub:batchUpdateFindings",
      "Next": "End"
    }
  }
}