AWS WAFログ解析に利用するAthenaクエリパターンまとめてみた

AWS WAFのログをAthenaで解析する際に役立つクエリパターンをまとめました。AWS WAFを導入する際にはログを解析して誤検知を見つけて安全にリリースしましょう。ログ取得の方法についてはリンクにあるブログを参照してください。
2018.07.05

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

こんにちは、臼田です。

みなさん、AWS WAF利用してますか?

今回はAWS WAFから取得したログをAthenaを利用して解析してみます。ログの取得方法は下記を参照してください。

AWS WAFのログを取得するCloudFormationテンプレートv2作ってみた

また、Athenaの基本的な使い方は下記を参照してください。

[新サービス]S3上のデータをSQLクエリで取得する、Amazon Athenaを試す #reinvent

テーブル作成

下記クエリでテーブルを作成します。S3バケットは環境に合わせて変更してください。

CREATE EXTERNAL TABLE IF NOT EXISTS waflogs
(
Action  string,
Request struct <
    ClientIP:string,
    Country:string,
    HTTPVersion:string,
    Headers:array < struct < Name:string, Value:string > >,
    Method:string,
    URI:string
>,
`Timestamp` timestamp,
RuleId string,
RuleName string,
Weight    int
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://waf-logs/';

ここで作成するテーブルは純粋なAWS WAFのサンプルログではなく、上記ログ取得スクリプトで取得したもののためRuleIDとRuleNameが追加され、Timestampも加工されていますので、別の手法で取得したログを解析する場合にはそのあたりを踏まえて変更してください。

カラムの説明

作成したテーブルのカラムについて説明します。

  • Action: WAFで処理したアクションで、ALLOW, BLOCK, COUNTのいずれか
  • Request: WAFが受け取ったリクエストの構造体。内部にリクエストの下記項目ごとのデータを持つ
    • ClientIP: クライアントIP
    • Country: 国コード2文字 (JP, US等)
    • HTTPVersion: HTTPバージョン
    • Headers: 各ヘッダの配列。中身はName, Valueの構造体。
    • Method: HTTPメソッド
    • URI: URI
  • Timestamp: ログのタイムスタンプ
  • RuleId: ログを出力したルールのID
  • RuleName: 上記ルールの名前
  • Weight: ログの関連性を表すweight

よく使うクエリ

とりあえず一覧

SELECT * FROM waflogs;

timestampによる絞り込み

SELECT * FROM waflogs where timestamp > timestamp '2018-07-03 05:17:00';

COUNTもしくはBLOCKのログ

ALLOWを確認したいことはあまりなく、基本的にはCOUNTもしくはBLOCLになったログを確認するためALLOWのみ除外する書き方をしています。どちらか片方しかなければ、=で決め打ちでもいいと思います。

SELECT * FROM waflogs WHERE action <> 'ALLOW';

COUNTもしくはBLOCKかつ日本からのログ

露骨に海外からのリクエストでBLOCK等していたら適切な動作だと判断しやすいですが、誤検知の可能性があるログを洗い出すためにJPで絞り込みます。

SELECT * FROM waflogs WHERE action <> 'ALLOW' AND request.country = 'JP';

この後出てきたログのURIやヘッダ、送信元IPなどから正常なリクエストに対する誤検知なのかを判断し、必要であれば正規表現のConditionを作りマネージドルールより手前にALLOWのルールとして追加します。

また、例えばwordpressの管理画面に対する通信で誤検知が多い場合には、送信元IPが確定していたらそれらのみALLOWするルールを追加することにより対応することもできるので、信頼できる送信元を登録しておくのもありです。

ルール毎のログ数の集計

SELECT RuleName, RuleId, COUNT(RuleId) AS count FROM waflogs GROUP BY RuleName, RuleId;

国毎のログ数の集計

JP以外が多いと、気になりますね。明らかに必要なければGeoIPのルールを手前に入れて止めることも検討します。

SELECT request.country, COUNT(request.country) AS count FROM waflogs GROUP BY request.country;

クライアントIP毎のログ数の集計

特定のクライアントIPから不適切な通信が多い場合には個別にIPブロックのルールを入れることも検討します。

SELECT request.clientip, COUNT(request.clientip) AS count FROM waflogs GROUP BY request.clientip;

まとめ

AWS WAFのログを解析する際のクエリパターンをまとめてみました。

正直そんなに複雑なサイトでなければWAFマネージドルールであまり誤検知することは無いと思いますので、サクッとクエリをかけてチューニングして運用を楽にしましょう。