AWS WAFのログをFirehoseでS3に出力しブロックログをS3Selectで確認してみた
はじめに
AWSチームのすずきです。
AWS WAF のアップデートにより、リクエストされたHTTPヘッダーと関連するWAFルール情報が含まれるアクセスログを Amazon Kinesis Data Firehose を利用し S3などに出力する事が可能になりました。
早速、リリースされたAWS WAF の包括的なログ記録機能と、出力されたログをS3 Selectを利用して確認する機会がありましたので、紹介させていただきます。
Firehose設定
AWS WAFのログ出力先となる Amazon Kinesis Data Firehoseと、ログ保管場所として利用するS3バケットの設置を行います。
- Firehoseのストリーム名は「aws-waf-logs-」で開始する必要があります。
- Firehoseと同じリージョンにログ出力先として利用するS3バケットを作成しました
- 今回、データ加工は省略しました。
- Firehoseの出力先は「Amazon S3」としました。
- 今回はテストの為、FirehoseのS3出力は最短(60秒)設定としました。
- S3、Athena、S3 Selectのコストの抑制の為、GZIP圧縮は有効としました。
- 確認画面
Monitoring
- 毎秒数百単位のリクエストが発生するWAFのログ出力先として利用する場合、設定実施後、Firehose Streamのメトリックを確認する事をおすすめします。。
- 東京リージョンのFirehoseの配信ストリームは、1,000 レコード/秒、1,000 トランザクション/秒、1 MiB/秒 の上限が設定されています。これに抵触する可能性がある場合、スロットルによるログ取得漏れを避けるため、AWSサポートへの上限緩和申請を実施してください。
AWS WAF設定
- ログ記録を有効にするACLを選択、「Logging」タブが追加されました。
- 先程用意した、「Kinesis Data Firehose」のストリーム名を選択します。
- HTTPリクエストヘッダのログ出力除外設定も可能です。
- 認証関連情報などログ記録が望ましくない場合や、ログ出力サイズの削減に利用出来ると思われますが、今回は省略しました。
- ログ設定後、設定内容が確認出来るようになります。
S3ログ確認
Kinesis Data Firehose経由でS3に出力されたAWSWAFのログ、S3 Selectを利用して確認してみました。
S3 Select
- AWS WAFのログはJSON形式、今回、FirehoseでGZIP圧縮を有効としたので、その指定を行います。
- プレビューでWAFログである事を確認後、
BLOCKログ
- 特定IPアドレスからのアクセスをブロックするルールで遮断したリクエストの抽出を試みました。
- SQL 式
1 | select * from S3Object s where s."action" = 'BLOCK' limit 1 |
- 出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | { "timestamp" : 1535787146518, "formatVersion" : 1, "webaclId" : "xxx-xxx-xxx-xxx-xxx" , "terminatingRuleId" : "xxx-xxx-xxx-xxx-xxx" , "terminatingRuleType" : "REGULAR" , "action" : "BLOCK" , "httpSourceName" : "ALB" , "httpSourceId" : "xxx-xxx/xxx-n-xxx-xxx/xxx" , "ruleGroupList" : [ { "ruleGroupId" : "xxx-xxx-xxx-xxx-xxx" , "terminatingRule" : null , "nonTerminatingMatchingRules" : [] } ], "rateBasedRuleList" : [], "nonTerminatingMatchingRules" : [], "httpRequest" : { "clientIp" : "xxx.xxx.xxx.xxx" , "country" : "JP" , "headers" : [ { "name" : "Host" , "value" : "dev.classmethod.jp" }, { "name" : "Content-Length" , "value" : "0" }, { "name" : "pragma" , "value" : "no-cache" }, { "name" : "cache-control" , "value" : "no-cache" }, { "name" : "user-agent" , "value" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.72 Safari/537.36" }, { "name" : "accept" , "value" : "image/webp,image/apng,image/*,*/*;q=0.8" }, { "name" : "referer" , }, { "name" : "accept-encoding" , "value" : "gzip, deflate, br" }, { "name" : "accept-language" , "value" : "ja,en-US;q=0.9,en;q=0.8" }, { "name" : "cookie" , "value" : "_ga=GA1.2.xxxx.xxxx; CookieConsent=-1; visitor_idxxxx=xxxx; (以下略)" } ], "uri" : "/favicon.ico" , "args" : "" , "httpVersion" : "HTTP/2.0" , "httpMethod" : "GET" , "requestId" : null } } |
ALLOW
- WAFを通過したリクエストについても確認が可能です。
-
SQL 式
1 | select * from S3Object s where s."action" = 'ALLOW' limit 1 |
- 出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | { "timestamp" : 1535787114374, "formatVersion" : 1, "webaclId" : "xxx-xxx-xxx-xxx-xxx" , "terminatingRuleId" : "Default_Action" , "terminatingRuleType" : "REGULAR" , "action" : "ALLOW" , "httpSourceName" : "ALB" , "httpSourceId" : "xxx-xxx/xxx-n-xxx-xxx/xxx" , "ruleGroupList" : [ { "ruleGroupId" : "xxx-xxx-xxx-xxx-xxx" , "terminatingRule" : null , "nonTerminatingMatchingRules" : [] } ], "rateBasedRuleList" : [], "nonTerminatingMatchingRules" : [], "httpRequest" : { "clientIp" : "54.251.31.xxx" , "country" : "SG" , "headers" : [ { "name" : "Host" , "value" : "dev.classmethod.jp" }, { "name" : "User-Agent" , "value" : "Amazon-Route53-Health-Check-Service (ref xxx-xxx-xxx-xxx-xxx; report http://amzn.to/1vsZADi)" }, { "name" : "Accept" , "value" : "*/*" }, { "name" : "Accept-Encoding" , "value" : "*" } ], "uri" : "/xxx/" , "args" : "" , "httpVersion" : "HTTP/1.1" , "httpMethod" : "GET" , "requestId" : null } } |
まとめ
AWS WAF、これまでもサンプルとして提供される情報をLambdaなどを用いて定期的に回収する事で、 ログとしてS3に保存する事は可能でしたが、取得期間、件数などの制限や、設置や維持管理などの課題を伴うものでした。
今回、AWS WAFの包括ログ出力機能がリリースされた事で、 ルールの誤判定などがあった場合でも、原因ルールの特定や回避が実施しやすくなり、 AWS WAF導入の敷居が下がる事が期待できると思われます。
また、これまでELBやCloudFrontのアクセスログでは取得できなかったヘッダー情報、WAFのログから取得出来るようになりました。 LambdaやKinesis Data Analyticsなどを活用した望まれない不正アクセスの検出や、カスタムWAFルールへのニアリアルタイム反映なども、実現できる可能性が高まったと思われます。
AWS WAFのS3へのログ出力は、Amazon Kinesis Data Firehoseの利用費(東京:1GBあたり0.036USD)とS3の費用のみで利用できます。
毎分平均1MB、1時間60MB、1日1.44GB、1ヶ月(30日)43.2GBのログが発生する場合、Firehoseの月額利用費は1.5USD。 S3利用費もFirehoseのGZIP圧縮を利用することでS3ストレージ消費は4GB程度、ライフサイクルで30日保持した場合、0.1USD(4GB×0.025USD)と廉価な利用が可能ですので、ぜひご活用ください。