Techfirm Cloud Architect Blog

テックファーム株式会社クラウドインフラグループのブログ

AWS WAFでブロックしたルールをAmazon Athenaで検索する

はじめに

AWS WAFの運用では、ログを分析する機会が多いと思います。
前回の記事「AWS WAFでカウントモードで検知したルールをAmazon Athenaで検索する」では、カウントモードで検知したルールをAmazon Athenaで検索するクエリについて紹介しました。
本稿では、ブロックしたルールを検索する方法を紹介したいと思います。

ブロックされたリクエストのログ

リクエストがブロックされたとき、下記5つのフィールドにどのような情報が記録されるのか説明します。
なお、action、terminatingruleid、terminatingruletypeの3つは別ruleGroupListの下もありますが、ここではトップレベルのフィールドについて説明します。

  • action
  • terminatingruleid
  • terminatingruletype
  • rateBasedRuleList
  • ruleGroupList

actionフィールド

トップレベルにあるactionフィールドには、リクエストに対して最終的に適用されたアクションが記録されます。
“BLOCK”と記録されているものがブロックされたリクエストです。

terminatingruleidフィールド

このフィールドには、リクエストを終了したルールが記録されます。
リクエスト終了ルールがグループに属している場合は、グループの名前が記録されます。

terminatingruletype フィールド

ブロックに該当したルールが属するルールグループの種類が記録されます。
たとえば、マネージドグループの時は"MANAGED_RULE_GROUP"、サードパーティーや自作したルールの場合は"GROUP"と記録されます。
グループではない場合、レートベースの場合の"RATE_BASED"や、"REGULAR"などがあります。

rateBasedRuleList フィールド

このリクエストで動作したレートベースのルールのリストが記録されます。
ただし、レートベースのルールがルールグループの属している場合は、このフィールドには何も記録されません。
また、レートベースのルールがブロックルールとなった場合は、terminatingruleidと、rateBasedRuleList内のrateBasedRuleNameには同じものが記録されます。
rateBasedRuleListのDDLは下記の様になります。

`ratebasedrulelist`
  array <
    struct <
      ratebasedruleid: string,
      limitkey: string,
      maxrateallowed: int
    >
  >,

ruleGroupList フィールド

リクエストに対して動作したルールがグループに属している場合はこのフィールドにルールのリストが記録されます。
このフィールド内のterminatingruleという項目に、ブロックしたルールの情報が入っています。
ruleGroupListの、ブロックしたルールに関するフィールドのDDLは下記となります。

`rulegrouplist` array <
  struct <
    rulegroupid: string,
    terminatingrule: struct <
      ruleid: string,
      action: string,
      rulematchdetails: array <
        struct <
          conditiontype: string,
          sensitivitylevel: string,
          location: string,
          matcheddata: array < string >
        >
      >
    >
  >
>
terminatingruleのデータ構造

リクエストがブロックされた時、ruleGroupListの中のterminatingruleにブロックしたルールの情報が記録されます。
terminatingruleの構造はこのようになります。

terminatingrule={
  ruleid=リクエストに一致したルールの ID,
  action=BLOCK,
  rulematchdetails=null
}

ブロックしたルールをAthenaで検索する

ブロックしたルールを検索するクエリを紹介します。
取得件数が膨大になる場合は、日付を指定したり、limitで取得件数を指定してください。

terminatingruleidを取得する

もっともシンプルなのはこのようなクエリです。
ブロックされたterminatingruleidのみを取得します。

SELECT
    terminatingruleid
FROM "waf_logs"
WHERE action='BLOCK'
AND DATE_FORMAT(FROM_UNIXTIME(timestamp/1000, 'Asia/Tokyo'), '%Y-%m-%d') = '2024-01-01'

rateBasedRuleListを取得する

ルールグループに属さないレートベースのルールでブロックされた場合、下記の様なクエリでratebasedrulelistの中身を取得できます。

SELECT
    t1.rateBasedRuleID,
    t1.rateBasedRule
FROM "mynavi_agent_waf_logs"
CROSS JOIN UNNEST(ratebasedrulelist) AS t(t1)
WHERE action = 'BLOCK'
AND terminatingRuleId = t1.rateBasedRuleName
AND DATE_FORMAT(FROM_UNIXTIME(timestamp/1000, 'Asia/Tokyo'), '%Y-%m-%d') = '2024-01-01'

ruleGroupListを取得する

ルールグループに属すルールでブロックされた場合、下記の様なクエリでルールの情報を取得できます。

SELECT
    t1.terminatingrule.ruleId
FROM "waf_logs"
CROSS JOIN UNNEST(rulegrouplist) AS t(t1)
WHERE t1.terminatingrule.action='BLOCK'
AND DATE_FORMAT(FROM_UNIXTIME(timestamp/1000, 'Asia/Tokyo'), '%Y-%m-%d') = '2024-01-01'

ブロックした件数が多かったルールを取得するには下記の様なクエリを実行します。

SELECT
    count(t1.terminatingrule.ruleId) as count,
    t1.terminatingrule.ruleId
FROM "waf_logs"
CROSS JOIN UNNEST(rulegrouplist) AS t(t1)
WHERE t1.terminatingrule.action='BLOCK'
AND DATE_FORMAT(FROM_UNIXTIME(timestamp/1000, 'Asia/Tokyo'), '%Y-%m-%d') = '2024-01-01'
GROUP BY t1.terminatingrule.ruleId
ORDER BY count DESC

さいごに

ブロックしたルール情報は比較的分かりやすい構造でログに記録されていますが、グループに属さないルールはrulegrouplistから情報を得られないため、複数回クエリを実行する必要があります。
取得したい情報に応じて、紹介したクエリをうまく活用してみてください。