こんにちは。インフラチームの倉橋です。
みなさんWAF導入してますか?
弊社ではAWSが提供している「AWS WAF」を利用しています。
今回は、そのWAF導入による「誤検知」を防ぐために活用した「カウントモード」について書いていきます。
AWS WAFの「カウントモード」
カウントモードとは、
- ルール一致時に検知はするが「許可」も「拒否」も行わない
ものとなります。
この機能を適用することで事前に「どのようなリクエスト」「どのようなルールに一致」しているかを知ることができます。
「正常なリクエストをブロック」する「誤検知」を事前に知ることができる素晴らしい機能です。
「カウントモード」の適用方法
カウントモードを適用する方法は、
- ルール全体を「カウントモード」とする方法
- 一部ルールを「カウントモード」とする方法
の2種類があります。
それぞれについて、
- AWSコンソール
- CloudFormationテンプレート
で適用する方法を以下に記載していきます。
※今回対象としているルールは「AWSマネージドルール」となります。
AWSマネージドルールについては以下リンクを参照
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/aws-managed-rule-groups.html
ルール全体を「カウントモード」とする方法
AWSコンソール
- ルール編集画面を開きます
- 「Override rule group action - optional」にチェックを入れます
- 保存します
- ルール詳細で「Override rule group action to count」と設定が入っていればOK
CloudFormationテンプレート
テンプレートで指定する場合は OverrideAction:
を指定することで適用できます。
ルール1つ1つに指定する必要があります。
Resources: # Client WebACL for Regional CountModeWAF: Type: AWS::WAFv2::WebACL Properties: Name: CountModeWAF Description: Protect Client API for Regional Service. Scope: REGIONAL DefaultAction: Allow: {} VisibilityConfig: MetricName: CountModeWAF CloudWatchMetricsEnabled: true SampledRequestsEnabled: true Rules: - Name: AWS-AWSManagedRulesAmazonIpReputationList Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesAmazonIpReputationList # ココから OverrideAction: Count: {} # ココまで VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: AWSManagedRulesAmazonIpReputationList SampledRequestsEnabled: true
一部ルールを「カウントモード」とする方法
AWSコンソール
- ルール編集画面を開きます
- 「カウントモード」としたいルールの「Count」にチェックを入れます
- 保存します
- ルール詳細で「Count」と設定が入っていればOK
CloudFormationテンプレート
テンプレートで指定する場合は ExcludedRules:
で「カウントモード」にするルールを指定することで適用できます
OverrideAction:
は None
で指定します。
こちらもルール1つ1つに指定する必要があります。
Resources: # Client WebACL for Regional CountModeWAF: Type: AWS::WAFv2::WebACL Properties: Name: CountModeWAF Description: Protect Client API for Regional Service. Scope: REGIONAL DefaultAction: Allow: {} VisibilityConfig: MetricName: CountModeWAF CloudWatchMetricsEnabled: true SampledRequestsEnabled: true Rules: - Name: AWS-AWSManagedRulesCommonRuleSet Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesCommonRuleSet # ココから ExcludedRules: - Name: NoUserAgent_HEADER - Name: SizeRestrictions_BODY OverrideAction: None: {} # ココまで VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: AWSManagedRulesCommonRuleSet SampledRequestsEnabled: true
「カウントモードの」ログ出力と監視
上記の方法で「カウントモード」の適用ができた後は監視フェーズに移ります。
監視する方法として以下があります。
- サンプルによる監視
- WAFログによる監視
「サンプルによる監視」はルール一致した一部のリクエストを監視します。
「WAFログによる監視」はCloudWatchやAthenaでログを監視します。
全てを監視するにはログを確認する必要があります。
WAFログの出力方法
WAFログはS3とCloudWatchLogsへの出力に対応しています。
今回はS3出力を取り扱います。
S3出力設定は2021年11月に WAFからS3 へ直接出力できるアップデートがあり、より簡単に設定できるようになりました!
それ以前は間に KinesisFirehose が必要でした。
S3出力
- ログ出力先のS3バケットを作成します
- バケット名の先頭は
aws-waf-logs-
で始める必要がある点に注意
- バケット名の先頭は
- WebACLの「Logging and metrics」を開きます
- 「Logging destination」で「S3 bucket」にチェックをいれます
- バケットは 1. で作成したバケットを指定します
- 「Filter logs」の設定を行い出力されるログを「Block」および「Count」だけに絞ります
- 「Allow」を出力する場合リクエスト数が多いサービスと、S3ストレージコストに影響を与える可能性があるので要注意です
- 設定を保存します
- S3にログが出力されているか確認します
WAFログの監視方法
S3へログ出力されるようになったので次にログの監視に入ります。
S3のログは Athena でクエリをかけて閲覧します。
Athenaテーブルの作成
S3にあるデータにクエリをかけるためにはテーブルを作成する必要があります。
テーブル作成方法はAWS公式ドキュメントに記載がありますのでご参照ください。
今回はパーティション管理を自動化できる「パーティション射影」を使用したテーブル作成を行っています。
「パーティション射影」を使うことでパーティションが自動化され、いつでも最新のログをクエリすることが可能となるのです。(便利ですね)
Athenaでクエリ
テーブルの作成ができたらクエリをかけてログを閲覧していきます。
クエリは以下を作成しました。
with dataset as ( select webaclid, nonterminatingmatchingrules, httpsourcename, httpsourceid, labels, terminatingrulematchdetails, httpRequest.clientip, httpRequest.country, from_unixtime(timestamp / 1000, 'Asia/Tokyo') AS JST, httprequest from [table] where day in ('2021/11/02') and webaclid = '[webaclid]' ) SELECT webaclid, nonterminatingmatchingrule.ruleid as ruleid, httpsourcename, httpsourceid, label.name as label, terminatingrulematchdetails, httpRequest.clientip, httpRequest.country, JST FROM dataset CROSS JOIN UNNEST(labels) as t(label) CROSS JOIN UNNEST(nonterminatingmatchingrules) as t(nonterminatingmatchingrule)
今回参考にするログ項目は以下になります。
参考にするログ項目
項目 | 内容 | 備考 |
---|---|---|
timestamp | タイムスタンプ (ミリ秒単位) | |
webaclid | ウェブ ACL の GUID | このIDでWebACLを識別します ex) arn:aws:wafv2:us-east-1:[account_id]:global/webacl/[WebACL_NAME]/[WebACL_ID] |
terminatingrulematchdetails | リクエストに一致した終了ルールに関する詳細情報 SQLi および XSS に一致するルール時だけ出力 |
|
httpsourcename | リクエストの送信元 | CloudFront, ALB などの識別に使用 ex) CF,APIGW,ALB,APPSYNC |
httpsourceid | ソース ID | 関連付けされたリソースのIDが入る ALB,APIGWなどの識別に使用 |
nonterminatingmatchingrules (JSON配列) | リクエストに一致するルールグループ内の終了しないルールのリスト | カウントモードでどのルールに一致したか解析するために使用 |
labels | ウェブリクエスト上のラベル (JSON配列) | どのルールによってリクエストが評価されたか解析するために使用 |
httprequest.clientip | クライアントIP | |
httprequest.country | 国 | |
httprequest | リクエストに関するメタデータ (JSONオブジェクト) |
より詳細な情報はAWS公式ドキュメントを参照ください。
ログの精査
出力したログの確認方法ですが、
labels
がどのルールに一致したか確認するhttprequest
を見てリクエストが正常か異常かを判断する
がベースになるかと思います。
サービスによって何が正常であるか異なってくるので、それぞれのサービスの観点を見つけていくことが大事だと思います。
ルールの見直し
最後に「カウントモード」の結果を受けてルール修正を行いましょう。
その後、修正したルールによるログを再度監視することも忘れずに。
おわりに
AWS WAFの「カウントモード」について書いていきました。
サービス影響を出さないためにも、AWS WAF適用時には「カウントモード」で事前確認は必須であると考えいますので、ぜひ活用していきましょう!