AWS WAF のログからUser-Agent(ユーザーエージェント)を抽出して分析したい
AWS WAF のログを CLoudWatch Log Insights で分析した際に、User-Agent (ユーザーエージェント)の抽出に苦労したので、躓いた点と解決までの流れを記したいと思います。
まず、以下のクエリでどのようなログが出ているかを確認してみます。
1 2 3 |
fields @timestamp, @message | sort @timestamp desc | limit 20 |
少し見づらいですが、httpRequest.headers.3 に今回取得したい User-Agent (ユーザーエージェント)が格納されていることが分かります。
- httpRequest.headers.3.name: User-Agent
- httpRequest.headers.3.value: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4240.193 Safari/537.36
目的のログの値は確認できましたが、ここで気になる点があります。
それは、httpRequest.headers.1, httpRequest.headers.2, httpRequest.headers.3 … と複数 httpRequest.headers が存在することです。
他のログを確認したところ、どうやら必ず httpRequest.headers.3 に User-Agent (ユーザーエージェント)が入っているわけではないようです。
httpRequest.clientIp のように決まったフィールドに入っていればよいのですが、User-Agent (ユーザーエージェント) や Host などの情報は httpRequest.headers に順不同に入れられています。
解決策
では、CloudWatch Log Insights で分析する際に、どのようにして WAF のログから User-Agent (ユーザーエージェント)を取得して使用するかを記します。
実は、 @message を parse することで取得が可能です。以下は @message の一部です。
1 |
,{"name":"User-Agent","value":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4240.193 Safari/537.36"}, |
では、 @timestamp, httpRequest.clientIp, httpRequest.contry と User-Agent を取得してみます。
1 2 3 |
fields @timestamp, httpRequest.clientIp, httpRequest.country | parse @message '"name":"User-Agent","value":"*"' as ua | limit 20 |
注意点として、“User-Agent”, “user-agent” 大文字小文字を区別する必要があり、どちらか一方がログに入っていることがあります。
そのため以下のように、”User-Agent”, “user-agent” 別々に抽出し ua1, ua2 に格納します。どちらか一方は値が空になるため coalesce を使用して ua に格納します。
更に今回は、IP、 User-Agent ごとにどのくらい WAF に検知されていれるかカウントしてみます。
1 2 3 4 5 6 |
fields @timestamp, httpRequest.clientIp, httpRequest.country | parse @message '"name":"User-Agent","value":"*"' as ua1 | parse @message '"name":"user-agent","value":"*"' as ua2 | stats count(httpRequest.clientIp) as count by httpRequest.clientIp, httpRequest.country, coalesce(ua1, ua2) as ua | filter count > 1 | sort count desc |
まとめ
CloudWatch Log Insights で WAF のログを分析し、IP と User-Agent ごとにどのくらい検知されているかカウントするところまでやってみました。
初めは User-Agent をうまく抽出することに悩み、更にそれぞれ “User-Agent” と “user-agent” のように大文字小文字の違いがありどのようにパースするかにも苦労しました。
この記事が誰かの役に立てば幸いです。