Amazon Web Services ブログ

Amazon CloudWatch Logs による AWS WAF ログの分析

本記事は、「Analyzing AWS WAF Logs in Amazon CloudWatch Logs」と題された記事の翻訳となります。

この投稿では、Logs InsightsContributor Insightsメトリクスフィルターなどの Amazon CloudWatch の機能を使用して、AWS ウェブアプリケーションファイアウォール (AWS WAF) ログを分析し、ダッシュボードを作成、アラームを生成する方法を説明します。 CloudWatch Logs Insights は、Amazon CloudWatch Logs で WAF ログをインタラクティブに検索および分析することにより、セキュリティインシデントと誤検知を特定する方法を提供します。WAF コンソールには、デフォルトでLogs Insights を使用して WAF ログを分析するためのサンプルクエリがいくつか用意されています。これを拡張するには、独自のクエリを記述します。Contributor Insights は上位 N のコントリビューターのダッシュボードを作成するコスト効率の高い方法を提供し、異常値、上位の IP アドレス、URI、Terminating ルール ID、ユーザーエージェントなどを簡単に表示することで、WAF の継続的な分析を実行するための簡単なプラットフォームを提供します。メトリクスフィルターを使用すると、条件を定義し、WAF ログ内の特定のパターンを見つけることができます。これを使用して、ログイベント内の語句と照合し、ログデータをメトリクスに変換してアラームを生成できます。

以前は、WAF ログを Amazon Kinesis Data Firehose 経由で Amazon OpenSearch、ダッシュボード用のサードパーティソリューション、または Amazon Athena と組み合わせた Amazon Simple Storage Service (Amazon S3) に送信して、ログ分析を行う必要がありました。お客様には大量の受信ログがあり、これらの構成ではログ分析とダッシュボードに複数のサービスを統合する必要があるため、ログの分析が困難になります。また、これには費用がかかり、お客様はソリューションを最新の状態に保つために別々のチームを必要としていました。これを簡略化するために、メトリクスフィルター、Logs Insights、異常検出、Contributor Insights などの CloudWatch の機能を使用して、ログを直接 CloudWatch に送信し、ログ分析、ダッシュボードの作成、アラームの表示を 1 つのペインで行うことができるようになりました。

セットアップ

CloudWatch Logs に送信される WAF ログを設定するには、以下のステップを使用します。

  1. AWS CloudWatch コンソールで、”ロググループ”に移動します
  2. “ロググループを作成”を選択します
  3. ロググループにわかりやすい名前を付けます。ロググループ名は aws-waf-logs-で始まる必要があります (例: 下のスクリーンショットに示すように aws-waf-logs-test)。要件に合わせて “保持期間の設定”を選択し、”作成”を選択します
  4. AWS WAF コンソールに移動し、ログを有効にする ウェブ ACL を選択し、”Logging and metrics” → “Edit” に移動します
  5. “Enable logging” ページで、ログの送信先として “CloudWatch Logs” ロググループを選択し、ステップ 3 で作成したロググループを選択します
  6. フィールドを編集したり、Web リクエストをフィルタリングしたりする場合は、必要に応じて設定を選択し、”Save” をクリックします
  7. これで、CloudWatch Logs Insights コンソールが “CloudWatch Log Insights” タブ内で有効になっていることがわかります
  8. または、次の AWS CloudFormation テンプレートを使用して、CloudWatch ロググループを宛先としてロギングを有効にすることもできます

図 1: CloudWatch コンソールでロググループを作成する

こちらの CloudFormation テンプレートを使用して、ウェブ ACL のログ記録を有効にできます。グローバルウェブ ACL (CloudFron ディストリビューション用) の場合は、テンプレートを us-east-1 にデプロイします。

CloudWatch を WAF ログの送信先として設定したら、次の手順に従って、CloudWatch Logs Insights を使用して受信ログを対話的に検索および分析できます。

  1. WAF コンソールで “Web ACLs” を選択し、WAF リソースを含むリージョンに変更します
  2. ロギングを有効にしたウェブ ACL 名を選択します
  3. “CloudWatch Logs Insights” タブを選択します

図 2: CloudWatch ロググループへの WAF ロギングの有効化

クエリエディタでは、次のように既定のクエリを実行できます。これにより、受信した最新の 20 個のログエントリと関連するタイムスタンプが表示されます。

fields @timestamp, @message
| sort @timestamp desc
| limit 20

さらに、クエリのリストから「最も頻繁に使用されるクエリ」を選択できます。これには、上位 100 の IP アドレス、上位 100 の国、上位 100 のユーザーエージェント、上位 100 のホスト、および上位 100 の terminating ルールなどが含まれます。

Log Insights

例 1: WAF コンソールからデフォルトのクエリを使用して上位 100 の IP アドレスを取得する

この例では、次のクエリを実行します。このクエリは、httpRequest から clientIp を抽出し、各 clientIp からのリクエスト数をカウントし、clientIp をリクエスト数の降順で並べ替え、アプリケーションへのリクエスト数が最も多い上位 100 の IP アドレスを表示します。

fields httpRequest.clientIp
| stats count(*) as requestCount by httpRequest.clientIp
| sort requestCount desc
| limit 100

クエリを選択して “Run query” を押下すると、”Logs” タブに IP アドレスとその数のリストが表示されます。”Visualization” タブに移動すると、”Line”、”Bar”、”Pie” から選択して結果を表示できます。

図 3: WAF コンソールでの上位 100 の IP アドレスのクエリ結果

WAF コンソールでは、上位 100 の国、ユーザーエージェント、ホスト、および Terminating ルールに対して同様のクエリを提供します。これらの上位 100 のリストは、ウェブ ACL をカスタマイズして、スパムなどの望ましくない可能性のあるトラフィックからアプリケーションを保護するのに非常に役立ちます。クエリを実行するときは特定の期間を設定する必要があります。クエリは 15 分後にタイムアウトします。さらに、ほぼリアルタイムで確認する必要がある場合、一定間隔で結果を更新するように設定できます。

WAF コンソールに表示されるサンプルクエリに加えて、ログを分析するためのカスタマイズされたクエリを記述できます。これについては、次のセクションで詳しく説明します。

例 2: カスタムルールの TerminatingRule または AWS マネージドルールグループのいずれかで、クロスサイトスクリプティング (XSS) または SQL インジェクションをトリガーしたパターンを検索する

カスタムルールまたは AWS マネージドルールグループの TerminatingRule で、クロスサイトスクリプティング (XSS) または SQL インジェクションをトリガーしたパターンを検索するクエリを次に示します。これにより、タイムスタンプ、クライアント IP アドレス、発信元の国、一致の詳細、およびリクエスト ID を含むエントリが返されます。

fields @timestamp
| parse @message ',"terminatingRuleMatchDetails":[*],' as terminatingRuleMatchData
| filter (terminatingRuleMatchData like /XSS/ or terminatingRuleMatchData like /SQL/)| display @timestamp, httpRequest.clientIp, httpRequest.country, terminatingRuleMatchData, httpRequest.requestId
 limit 100

例 3: ルールによってカウントされたすべてのリクエストの上位 10 のユーザーエージェントを取得する

このクエリは、User-Agent のキーと値のペアを探し、カウントされたリクエストをフィルタリングします。結果には、リクエスト数が最も多い上位 10 のユーザーエージェントが返され、各ユーザーエージェントの数が返されます。User-Agent キーでは大文字と小文字が区別されることに注意してください。

fields @timestamp, @message
| parse @message '{"name":"User-Agent","value":"*"}' as userAgent
| parse @message ',"nonTerminatingMatchingRules":[{"ruleId":"*","action":"*"' as rule, action
| filter action = "COUNT"
| stats count(*) as requestCount by userAgent
| sort requestCount desc
| limit 100

例 4: ルールグループ内の特定のルールによってカウントされたエントリ

このクエリは、リクエストがデフォルトアクションによって終了されたルールグループ内の特定のルールによってカウントされる 10 個のログエントリを検索します。この例の場合、使用される特定のルールは、ルールグループ内の NoUserAgent_HEADER です。「ruleId」フィールドを分析したいルール ID に変更できます。結果には、タイムスタンプ、クライアントIPアドレス、発信国、および今後の処理のための requestId が表示されます。

fields @timestamp
| filter (@message like 'excludedRules":[{"exclusionType":"EXCLUDED_AS_COUNT","ruleId":"NoUserAgent_HEADER"}]}' and @message like 'terminatingRuleId":"Default_Action"')
| parse @message '"ruleId":*}]}' as ruleMatchDetails
| display @timestamp, httpRequest.clientIp, httpRequest.country, ruleMatchDetails, httpRequest.requestId
|limit 10

図 4: 一致したルール ID とリクエスト ID を示す例 4 の Log Insights の結果

例 5: 無効なキャプチャを含む上位 100 件のリクエスト

AWS WAF Captcha は、ウェブリクエストが AWS WAF で保護されたリソースに到達する前に、ユーザーがチャレンジを正常に完了することを要求することで、不要なボットトラフィックをブロックするために使用できます。次のクエリを使用して、無効な captcha を含む上位 100 個のリクエストを検索できます。これは、リクエストが行われた時刻、IP アドレス、さらに処理するためのリクエストID、レスポンスコード、および詳細な分析のためのメッセージ全体を返します。

fields @timestamp, httpRequest.clientIp, httpRequest.requestId, captchaResponse.failureReason, @message
|filter captchaResponse.failureReason ='TOKEN_MISSING'
| sort @timestamp desc
| limit 100

さらに、実行するクエリをダッシュボードに追加して、トラフィックパターンを監視し、WAF トラフィックをより包括的に表示できます。

メトリクスフィルター

次のセクションでは、CloudWatch メトリクスフィルターをモニタリングとアラートに活用する方法について説明します。CloudWatch Logs でメトリクスフィルターを使用すると、ログイベント内の語句、フレーズ、または値を検索できます。語句、フレーズ、または値を見つけたら、CloudWatch メトリクスをインクリメントして、時間の経過に伴うカウントをキャプチャできます。オプションで、しきい値に達したときに通知またはアクションを実行する CloudWatch アラームを作成できます。

CloudWatch コンソールを使用してメトリクスフィルターを作成するには、こちらのガイドの手順に従ってください。

以下に、WAF ログのフィルターを作成するためのサンプルパターンをいくつか示します。変数「[i]」を正しい数値に置き換える必要があることに注意してください。たとえば、ウェブ ACL に 4 つのルールグループがあり、RuleGroupList [i] で 2 を選択すると、ウェブ ACL の 3 つ目のルールグループが表示されます。

パターン 1: 個々のルールではなく、ルールグループによってカウントされるすべてのリクエストを取得する場合は、AWS-AWSManagedRulesCommonRulesSet のカウントを調べるために以下を使用できます。監視するルールグループを置き換えて利用することができます。

{($.nonTerminatingMatchingRules[i].ruleId=AWS-AWSManagedRulesCommonRuleSet)}

パターン 2: 特定のルールグループによってブロックまたはカウントされたすべてのリクエストを取得します。

{$.ruleGroupList[i].terminatingRule.action=BLOCK}

パターン 3: このフィルタは、ルールグループ内の特定のルールによってブロックされたすべての要求を検索します。ルール ID SignalNonBrowserUserAgent は、監視するルール ID に置き換えることができます。

{($.ruleGroupList[i].terminatingRule.action=BLOCK)&&($.ruleGroupList[i].terminatingRule.ruleId=SignalNonBrowserUserAgent)}

メトリクスフィルターの作成に加えて、CloudWatch Log グループのフィルタを使用してログに対してアドホックフィルタリングを実行し、確認するリクエストを取得できます。

パターン 4: たとえば、このようなフィルターを使用して、ブロックされたリクエストを示すすべてのログを検索できます。

{$.action="BLOCK"}

また、メトリクスフィルターを使用して、ルールで カウントされたリクエストをすべて取得することもできます。

{$.nonTerminatingMatchingRules[i].action = "COUNT"}

パターン 5: このメトリクスフィルターパターンを使用して、ウェブ ACL のルールグループ内の特定のルールによってカウントされたリクエストを検索できます。

{($.ruleGroupList[i].excludedRules[i].exclusionType= "EXCLUDED_AS_COUNT")}

図 5: ルール内のカウントを確認するためのメトリクスフィルターパターンを CloudWatch コンソールで作成する

メトリクスフィルターを作成したら、次の手順に従って Amazon CloudWatch アラームを作成できます。作成したメトリクスフィルターの名前空間とメトリクス名を検索し、通知を受けるしきい値を設定できます。たとえば、Amazon Simple Notification Service(Amazon SNS)通知を SNS トピックに送信するアラームを作成できます。この例では、メトリクスカウントが 25 より大きい場合に設定してします。リクエストの数がしきい値を超えると、アラームは「Alarm」状態になり、アラートのためにイベントが SNS トピックに送信されます。

図 6: 設定したしきい値を超えると通知する Alarm を CloudWatch コンソールで作成する

図 7: CloudWatch コンソールで CloudWatch アラームを表示して、データポイントが設定されたアラームの静的しきい値を超えているかどうかを判断する

Contributor insights

Contributor insights は、上位 N のコントリビューターをダッシュボードに表示するためのコスト効率の高い方法を提供します。これを使用して時系列データを分析し、Webアプリケーションに誰がまたは何が影響しているかを理解し、異常値を特定し、IPアドレス、ユーザーエージェント、ホスト、Tarminating ルールなどのログのさまざまなフィールドに基づいてトップ トーカーをランク付けするのに役立ちます。1 つ以上の コントリビューターを使用してContributor insights ルールを作成し、フィルターを追加してリクエストのサブセットのみに適用できます。たとえば、ブロックされたリクエストの上位 IP アドレスのみを確認できます。このセクションでは、Contributor insights ルールの作成例をいくつか紹介します。

例: すべてのブロックされたリクエストの上位 10 の IP アドレスと URI の組み合わせを取得する

この例では、ブロックされたすべてのリクエストについて、IP と URI に基づいて上位 10 のコントリビューターを取得します。

次のログエントリに示すように、action = “BLOCK” であるリクエストの httpRequest.clientIp と httpRequest.uri を監視する必要があります。ルールを作成する手順は次のとおりです。

  1. CloudWatch コンソールで、”Contributor Insights” を選択し、”ルールを作成” を選択します
  2. ルールの作成ウィザードで、”カスタムルール” を選択します
  3. “ロググループ” で、前に作成した WAF ロググループの名前を選択します (例:aws-waf-logs-xxxx)
  4. “ログの形式” で “JSON” を選択します
  5. コントリビューション → キーの下で、コントリビュータタイプ httpRequest.clientIp と httpRequest.uri を入力します
  6. コントリビューション → フィルターで以下を使用します。
    1. 一致 (Match) → Action
    2. 状態 (Condition) → In
    3. 値 (Value) → BLOCK
  7. “集計” → “集計” で “カウント” を選択します
  8. “次へ” を選択します
  9. “ルール名” に、名前を入力します
  10. “名前と状態を指定” で、”次へ” を選択します
  11. 変更を確認して、”ルールを作成” を選択します

図 8: Contributor Insights ですべてのブロックされたリクエストの URI と IP アドレスを表示するためのコンポーネントを含む WAF ログエントリの例

図 9: Contributor Insightsのすべてのブロックされたリクエストの URI と IP アドレスを表示するための Contributor Insights ルール

図 10: ブロックされたすべてのリクエストの URI と IP アドレスを表示した Contributor Insights の結果

Contributor Insights コンソールで、”構文” (Syntax) タブを選択すると、JSON 形式のルール本文が表示されます。

図 11: JSON 形式のルールテンプレート

次の表に、WAF ログ分析に役立つContributor Insights ルールの例をいくつか示します。次の表に、ルールを作成するために “構文” (Syntax) タブにコピーして貼り付けることができる JSON テンプレートを示します。

ユースケース JSON テンプレートへのリンク
上位 10 の Terminating ルール ID を取得する link
レートベースのルールによってブロックされた上位 100 の IP アドレス link
すべてのブロックされたリクエストの上位 10 の IP アドレスと URI の組み合わせを取得する (上記の例) link
ブロックまたはカウントされたルールグループ内の上位 10 のルールを取得する link

Contributor Insights ルールを作成したら、それらをダッシュボードに組み合わせて、トップトーカーを簡単に表示および分析できます。こちらの CloudFormation テンプレートを使用して、Contributor Insights ルールを展開できます。

まとめ

この投稿では、CloudWatch Log Insights を使用して、WAF ログをインタラクティブに検索および分析することにより、セキュリティインシデントと誤検知を特定する方法を示しました。さらに、Contributor Insights を活用して上位 N のコントリビューター向けのダッシュボードを作成する方法を明らかにしました。これにより、WAF の継続的な分析を実行するための簡単なプラットフォームと、WAF ログの特定のパターンを見つけるためのメトリクスフィルターが提供されます。 CloudFormation テンプレートを使用して、CloudWatch Logs で WAF ロギングをセットアップする方法を説明し、Log Insights、Contributor Insights 、メトリクスフィルターなど、さまざまな CloudWatch の機能を使用して、提供された例を通じてさまざまな方法でデータを簡単に分析する方法を示しました。それに加えて、さまざまな有用な指標に対する監視とアラートを設定する方法を示しました。

本記事の翻訳は Edge Specialist Solutions Architect の 岡 が担当しました。原文はこちらです