はじめに
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から情報を得られないため、複数回クエリを実行する必要があります。
取得したい情報に応じて、紹介したクエリをうまく活用してみてください。