AWS WAF の COUNT モードのログをクエリする時に httprequest の host を取得したい

記事タイトルとURLをコピーする

この記事は約5分で読めます。

マネージドサービス部 佐竹です。
表題の通り、調査で AWS WAF のログの分析が必要となりましたが、必要なクエリがネットに落ちておらず独自に SQL を記載したため、そちらをご紹介します。

はじめに

AWS WAF のログ分析には Amazon Athena を利用する場面が多いでしょう。具体的には以下の AWS ドキュメントを参考にテーブルを作成し、SQL クエリを実行することが多い状況です*1

パーティション射影を使用して Athena で AWS WAF S3 ログ用テーブルを作成する

docs.aws.amazon.com

パーティショニングなしで AWS WAF ログのテーブルを作成する

docs.aws.amazon.com

今回はこのドキュメントのうち、後者の「パーティショニングなし」のパターンを利用しての調査を行った場合の記録になります。

AWS WAF のログ調査で困っていたこと

AWS WAF を COUNT モードのみで運用している状態では、リクエストは BLOCK されずに全てのルールを通過し、ログに ALLOW 且つ COUNT として出力されます。

これは AWS WAF の COUNT モードが終了アクション(terminating action)ではないためで、場合によっては複数のルールにカウントされる可能性があります。

この状態を絵にすると以下のようになります。

終了アクションがある場合の構成

終了アクションがある場合は都度終了される

全てカウントとした場合の構成

全てカウントモードの場合は、デフォルトアクションで許可される

今回は図の後者である「AWS WAF を COUNT モードのみで運用している状態」の話です。

Default_Action

この状態の時 AWS WAF のログを見ると、全てが「Default_Action」で「ALLOW」されているよう見えます。

CloudFront セキュリティダッシュボード

上記画面キャプチャーは以下のブログでもご紹介しております CloudFront セキュリティダッシュボードのものですが、画像の通り全て「Allowed」となっていることがこちらでも分かります。

blog.serverworks.co.jp

そして「COUNT」は Athena で SQL クエリを記載して調査する時に、「action」に記載がされません。ここが「困った」ポイントです。以下は先ほどと同じログの再掲です。

Default_Action

全てが「Default_Action」で「ALLOW」されている状態のログです。

「action」には終了アクションが入る想定であり、先に記載した通り COUNT は終了アクションではないためこの「action」が検索に利用できないこととなります。

ではどうすれば COUNT のログを調査できるでしょうか?

どうすれば COUNT のログが分析できるか?

ということで、 COUNT モードのログを調査することが可能な Amazon Athena で実績のある、実用性の高い SQL クエリを以下で紹介していきます。

まずは1つ目です。

① 既存のテーブル定義で利用できる調査用 SQL

SELECT
from_unixtime(timestamp / 1000, 'Asia/Tokyo') AS JST_timestamp,
httprequest.clientip,
httprequest.country,
httprequest.uri,
r.rulegroupid,
n.ruleid,
n.action,
n.rulematchdetails
FROM
"default"."waf_logs"
CROSS JOIN UNNEST(rulegrouplist) AS t(r)
CROSS JOIN UNNEST(r.nonterminatingmatchingrules) AS t2(n)
WHERE
n.action = 'COUNT'
LIMIT 10;

上記 SQL を実行頂ければ以下の画面キャプチャー通りの結果が返ります。

クエリ結果①

本クエリでも action を表示できていますが、これは UNNEST(r.nonterminatingmatchingrules) AS t2(n) で取得しているまた別の action の結果です。

この点については以下の AWS 公式ブログにある「1: “nonTerminatingMatchingRules”内に“action”:“COUNT” として記録」の周辺箇所も合わせてご覧ください。

aws.amazon.com

さて、先の SQL でも十分にワークはするのですが、私は1点どうしても追加したい情報がありました。それは httprequest 内に格納されている host 情報です。

ただし、この情報を取得する場合は AWS ドキュメントにある DDL ではうまく動作しないことがわかりました。そのため、DDL から見直した調査 SQL クエリを以下に記載します。

修正版のテーブル定義 (DDL)

CREATE EXTERNAL TABLE `waf_logs`(
`timestamp` bigint,
`formatversion` int,
`webaclid` string,
`terminatingruleid` string,
`terminatingruletype` string,
`action` string,
`terminatingrulematchdetails` array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
`httpsourcename` string,
`httpsourceid` string,
`rulegrouplist` array <
struct <
rulegroupid: string,
terminatingrule: struct <
ruleid: string,
action: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>
>,
nonterminatingmatchingrules: array <
struct <
ruleid: string,
action: string,
overriddenaction: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
challengeresponse: struct <
responsecode: string,
solvetimestamp: string
>,
captcharesponse: struct <
responsecode: string,
solvetimestamp: string
>
>
>,
excludedrules: string
>
>,
`ratebasedrulelist` array <
struct <
ratebasedruleid: string,
limitkey: string,
maxrateallowed: int
>
>,
`nonterminatingmatchingrules` array <
struct <
ruleid: string,
action: string,
rulematchdetails: array <
struct <
conditiontype: string,
sensitivitylevel: string,
location: string,
matcheddata: array < string >
>
>,
challengeresponse: struct <
responsecode: string,
solvetimestamp: string
>,
captcharesponse: struct <
responsecode: string,
solvetimestamp: string
>
>
>,
`requestheadersinserted` array <
struct <
name: string,
value: string
>
>,
`responsecodesent` string,
`httprequest` struct <
clientip: string,
country: string,
headers: array <
struct <
name: string,
value: string
>
>,
uri: string,
args: string,
httpversion: string,
httpmethod: string,
requestid: string,
fragment: string,
scheme: string,
host: string
>,
`labels` array <
struct <
name: string
>
>,
`captcharesponse` struct <
responsecode: string,
solvetimestamp: string,
failureReason: string
>,
`challengeresponse` struct <
responsecode: string,
solvetimestamp: string,
failureReason: string
>,
`ja3Fingerprint` string,
`oversizefields` string,
`requestbodysize` int,
`requestbodysizeinspectedbywaf` int,
`ja4Fingerprint` string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/prefix/'

LOCATION 's3://amzn-s3-demo-bucket/prefix/' は適宜修正ください。

diff

なお、上図は AWS ドキュメントに記載のある DDL との部分的な diff を示しているのですが「host: string」を追加することで「host」を httprequest.host として使いやすく処理しています。

② 修正したテーブル定義で利用できる調査用 SQL

上記の修正版 DDL で実行できる SQL が以下です。Select するカラムの順序は並び替えたため、先ほどと異なっております。

SELECT
from_unixtime(timestamp / 1000, 'Asia/Tokyo') AS JST_timestamp,
httprequest.clientip,
httprequest.country,
httprequest.uri,
httprequest.host,
r.rulegroupid,
n.ruleid,
n.action,
n.rulematchdetails
FROM
"default"."waf_logs"
CROSS JOIN UNNEST(rulegrouplist) AS t(r)
CROSS JOIN UNNEST(r.nonterminatingmatchingrules) AS t2(n)
WHERE
n.action = 'COUNT'
LIMIT 10;

この SQL を実行頂ければ以下の画面キャプチャー通りになります。

クエリ結果②

こうすることで httprequest の host も含めて COUNT モードの AWS WAF ログが分析できるようになり、調査に有用でしょう。

まとめ

本ブログでは AWS WAF の COUNT モードのログを調査のためにクエリする際、httprequest の host も合わせて取得したいという要望に応えるために DDL と SQL クエリを作成しましたので、本文にてご紹介しました。

以下がまとめです。

  • 通常の DDL を利用したシンプルな SQL では action に COUNT が含まれないため調査が難しい
  • UNNEST(r.nonterminatingmatchingrules) として COUNT モードのログを調査することが可能になる (SQL ①)
  • ただし httprequest の host を取得したい場合は DDL から改変すると良い
  • 改変版の DDL であれば httprequest.host として host の情報も調査に活用しやすくなる (SQL ②)

このブログが AWS WAF の調査を行っているどなたかに、ほんの少しでも役に立てば幸いです。

では、またお会いしましょう。

*1:S3 Select を使うことも過去ありましたが、本サービスは新規の AWS アカウントでは利用できないため割愛します

佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ

マネージドサービス部所属。AWS資格全冠。2010年1月からAWSを利用してきています。2021-2022 AWS Ambassadors/2023-2024 Japan AWS Top Engineers/2020-2024 All Certifications Engineers。AWSのコスト削減、最適化を得意としています。