Amazon AthenaでAWS WAF XSS/SQLiの詳細ログをクエリしてみた #reinvent

新しく追加されたterminatingRuleMatchDetailsのログフィールドをAmazon Athenaでクエリする方法についてまとめm
2020.01.05

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

こんにちは、臼田です。

みなさん、ログ分析してますか?(挨拶

AWS WAFでXSS/SQLiの詳細ログが出力されるようになったので、これをAmazon Athenaでクエリしてみました。詳細ログについては下記をご参照ください。

AWS WAFのログをAthenaで分析

AWS WAFのログはS3に保存されます。S3に保存されているデータを分析するにはAmazon Athenaを利用してクエリをかけるとやりやすいです。詳細は下記をご確認ください。

今回のログフィールドの追加に合わせてアップデートしました。

新しいCreate Table

上記記事も更新してありますが、新しいCreate Tableを書いておきます。

CREATE EXTERNAL TABLE IF NOT EXISTS waflogs
(
`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 's3://[バケット名]/';

変更点は今回追加されたterminatingRuleMatchDetailsのところです。

ちなみにformatVersionは一向に1のままです。何度かログフィールドが追加されていますが、追加だけで既存が壊れるような変更が無いので、1のままということかもしれません。

クエリしてみた

簡単なクエリは上述のブログを参照してください。

今回はterminatingRuleMatchDetailsを確認することにフォーカスを当ててSELECT文を考えてみました。

XSS/SQLiでBLOCKされたログとその詳細を確認するクエリ

SELECT
  from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST,
  groupList.ruleGroupId,
  groupList.terminatingRule.ruleId,
  ruleMatchDetails.conditionType,
  ruleMatchDetails.location,
  ruleMatchDetails.matchedData,
  httpRequest
FROM
  "default"."waflogs",
  UNNEST(terminatingRuleMatchDetails) t(ruleMatchDetails),
  UNNEST(ruleGroupList) t(groupList)
WHERE action = 'BLOCK' and groupList.terminatingRule.action = 'BLOCK' ;

ポイントはterminatingRuleMatchDetailsがArrayになっているのでUNNESTで展開していることと、合わせてruleGroupListに含まれるruleIdなどを確認するとルール名が明確になりわかりやすいためこれも展開していることです。

実際には下記のように表示されます。検知結果が適切かどうかを判断するための重要なデータはmatchedDataなので、この値に特に注目して確認するといいです。httpRequestを最後に入れていますが、環境に応じてもう少し詳細に出力したり、一旦結果の右上にあるボタンからCSVでダウンロードしてExcelなどでこねこねしていくといいでしょう。

まとめ

terminatingRuleMatchDetailsを調査するためのクエリを考えてみました。

誤検知の場合のホワイトリスト作成などに役に立つと思うので是非活用してください。