AWS WAFのログをCloudWatch Logs Insightsで分析する

2023.09.26

はじめに

私が担当している案件ではAWS WAFを使っています。以前はログをKinesis firehoseを使ってS3に出力してAthenaで分析していたのですが、CloudWatch Logsに直接出力できるようになったので、CloudWatch Logs Insightsで分析してみました。

クエリを使って分析する

CloudWatch Logs Insightsのクエリを使ってログを分析してみます。 クエリ構文の詳細はこちらをご覧ください。

時間を指定したい場合

時間を指定したい場合はCloudWatch Logsの右上のコントロールで設定します。タイムゾーンは UTC か Local に設定できます。

クエリ内で時間を指定したい場合はunixタイムスタンプをミリ秒単位にした値を以下のように指定します。YYYY-MM-DD のように文字列で指定する方法は見つけられませんでした。

fields @timestamp, @message
| filter tomillis(@timestamp) > 1695213000000
| sort @timestamp desc
| limit 20

ブロックされたリクエストを見たい場合

ブロックされたリクエストの情報を見たい場合は以下のクエリを実行します。時間、適用されたルール、HTTPメソッド、URI、国、IPアドレス、ユーザーエージェントなどの情報を取得しています。

fields 
  @timestamp,
  terminatingRuleId,
  httpRequest.httpMethod as method,
  httpRequest.uri as uri,
  httpRequest.country as country,
  httpRequest.clientIp as clientIp
| parse @message '{"name":"User-Agent","value":"*"}' as userAgent
| parse @message '"ruleId":"*",' as ruleId
| filter action='BLOCK'
| sort @timestamp desc
| display @timestamp, terminatingRuleId, ruleId, method, uri, country, clientIp, userAgent
| limit 100

method や uri が REDACTED と表示される場合はログから削除される設定になっているため、AWS WAFのログ設定画面で変更してください。

カウントされたリクエストを見たい場合

誤検知対策としてWAFのルールに該当してもすぐにブロックせず、カウントにして様子を見る場合もあるかと思います。その場合は以下のように書き換えます。

fields 
  @timestamp,
  httpRequest.httpMethod as method,
  httpRequest.uri as uri,
  httpRequest.country as country,
  httpRequest.clientIp as clientIp
| parse @message '{"name":"User-Agent","value":"*"}' as userAgent
| parse @message ',"nonTerminatingMatchingRules":[{"ruleId":"*","action":"*"' as rule, action
| filter action='COUNT'
| display @timestamp, rule, method, uri, country, clientIp, userAgent
| sort @timestamp desc
| limit 100

日別のブロック件数を調べたい場合

日別のブロック件数を集計したい場合は以下のようなクエリを実行します。ここではcount関数を使っています。日本時間にするために9時間足してから、datefloor関数で時間部分を切り捨てています。使える集計関数に関してはこちら、datefloorなどの日時関数はこちらをご覧ください。

fields
  @timestamp,
  toMillis(@timestamp)+60*60*9*1000 as millis,
  datefloor(millis, 1d) as jst_date
| stats count(*) by jst_date
| filter action = 'BLOCK'
| sort jst_date desc
| limit 10

ランキングを表示したい場合

以下はよく指定されるURIを知りたい場合のクエリになります。他にも多くのリクエストが来る国、IPアドレスなどが知りたい場合は httpRequest.uriの部分を httpRequest.country , httpRequest.clientIp に変更します。

fields httpRequest.uri
| stats count(*) as requestCount by httpRequest.uri
| sort requestCount desc
| limit 10

WAFの機能で攻撃をブロックする

分析した結果を基にWAFの機能を使って攻撃をブロックしていきます。

指定した国からのリクエストをブロックしたい場合は以下の記事をご覧ください。

AWS WAF v2 で特定の国からのアクセスをブロックしてみた

特定のIPアドレスからのリクエストをブロックする方法は以下の記事をご覧ください。

AWS WAFV2でIPアドレス制限してみた

NACLでも指定したIPアドレスからのリクエストをブロックできますが、デフォルトで20までしかIPアドレスを設定できないので注意してください。WAFで設定する場合はIPセット1つにつき10000まで設定できます。またセキュリティグループでは特定のIPアドレスからのリクエストを拒否することはできません。

最後に

今回調べたことは以上になります。最初はSQLが使えるAthenaで分析する方が楽そうだと思っていましたが、意外とすぐに慣れることができました。Athenaと違いテーブル作成する手間がないことと、監視、通知の設定が簡単にできるのがCloudWatch Logsのメリットでしょうか。今後もCloudWatch Logs Insightsで攻撃パターンを分析してサイトを保護していきたいと思います。

参考

Amazon Web Services ブログ - Amazon CloudWatch Logs による AWS WAF ログの分析