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を取り扱うための独自関数が多数用意されています。