AthenaでWAFのログからBLOCKされたルールの詳細を確認する

AWS01 April 2021

AWSのWAFを使用していて、どのリクエストが弾かれか?逆に許可されたかを厳密に知るためには、ログを貯める必要があります。
そのログは当たり前のようにS3に溜まっていくのですが、その時の探索方法のメモです。

参考サイト: Amazon AthenaでAWS WAF XSS/SQLiの詳細ログをクエリしてみた #reinvent

テーブル作成

createのクエリをAthenaのコンソールから実行します。

変数名 用途
YOUR_TABLE_NAME 作成したいテーブル名
YOUR_S3_BUCKET_URI 探索対象にしたいS3のURI
CREATE EXTERNAL TABLE IF NOT EXISTS YOUR_TABLE_NAME
(
`timestamp` bigint,
formatVersion int,
webaclId string,
terminatingRuleId string,
terminatingRuleType string,
action string,
terminatingRuleMatchDetails array < struct <
    conditionType: string,
    location: string,
    matchedData: array < string >
> >,
httpSourceName string,
httpSourceId string,
ruleGroupList array < struct <
    ruleGroupId: string,
    terminatingRule: struct < ruleId: string, action: string >,
    nonTerminatingMatchingRules: array < struct < action: string, ruleId: string > >,
    excludedRules: array < struct < exclusionType: string, ruleId: string > >
> >,
rateBasedRuleList array < struct < rateBasedRuleId: string, limitKey: string, maxRateAllowed: int > >,
nonTerminatingMatchingRules array < struct < action: string, ruleId: string > >,
httpRequest struct <
    clientIp: string,
    country: string,
    headers: array < struct < name: string, value: string > >,
    uri: string,
    args: string,
    httpVersion: string,
    httpMethod: string,
    requestId: string
>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION YOUR_S3_BUCKET_URI;

バケットのURIはどの階層まで掘ってもOK

WAFのログが蓄積されると以下のようなディレクトリパスでS3に格納されます。
~~/YYYY/MM/01
~~/YYYY/MM/02
~~/YYYY/MM/03

ここで、${YOUR_S3_BUCKET_URI}に指定するURIは以下のいずれでも問題ありません。

s3://~~/
s3://~~/YYYY/
s3://~~/YYYY/MM/
s3://~~/YYYY/MM/01

どの期間ごとにログ解析を行いたいかによって変更すれば良いということになります

例)日本からのアクセスでブロックされたルールの詳細を確認

selectのクエリを実行します。

変数名 用途
YOUR_DB_NAME テーブルのあるデータベース名
SELECT
  from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST,
  groupList.ruleGroupId,
  groupList.terminatingRule.ruleId,
  httpRequest
FROM
  YOUR_DB_NAME.YOUR_TABLE_NAME,
  UNNEST(ruleGroupList) t(groupList)
WHERE action = 'BLOCK' and groupList.terminatingRule.action = 'BLOCK' and httpRequest.country = 'JP';

UNNESTによりArrayで格納されたデータが分割される

UNNEST(ruleGroupList) t(groupList)

上記の指定にて、Array型であるruleGroupListが展開されjoinされます。
そのデータ1つ1つに対してアクセスするためには、

t(groupList)

t(アクセス変数)で指定したgroupListから取得可能です。

groupList.ruleGroupId,
groupList.terminatingRule.ruleId,

他にもAthenaには、ArrayやMapを取り扱うための独自関数が多数用意されています。

Amazon Athena を使用した SQL クエリの実行

tags: AWS