AWS WAFのチューニング手法
本記事の位置づけ
この記事は、AWS WAFを最初からBlockで入れて事故らせないためのチューニング手順を整理するものなのだ。
AWS Managed Rulesの選定、WCU計算、Countでの観測、誤検知調整、scope-down statement、label match、本番Block移行までを扱う。特定環境の完成設定ではなく、Web ACLを設計・調整するときに確認する観点の記録である。
WCUやManaged Rulesの内容は変更される可能性がある。導入前には、AWS WAFコンソール、ListAvailableManagedRuleGroups、DescribeManagedRuleGroup、公式ドキュメントで確認する。
結論
AWS WAFのチューニングでは、最初から全量ログや全ルール詳細を読む必要はないのだ。
実務では、次の順番で進める。
- 保護対象のアプリケーション特性を整理する。
- 必要なAWS Managed Rulesを選ぶ。
- WCUを計算する。
- まずCountで導入する。
- ログ、メトリクス、sampled requestsで検知状況を見る。
- 誤検知を個別ルール単位で調整する。
- scope-down statementやlabel matchで対象を絞る。
- ビジネスロジック上の妥当性を確認する。
- 問題ないルールからBlockへ移す。
重要なのは、「誤検知したルールを外す」ことではない。
より正確には、「誤検知した個別ルールをCount継続にし、最小範囲の例外に調整する」なのだ。
AWS Managed Rulesの全体像
AWS Managed Rulesは、AWSが管理するルールグループなのだ。
Web ACLに追加するだけで、一般的なWeb攻撃、既知の悪性入力、OSやアプリケーション固有の攻撃、IP reputation、Bot、アカウント不正利用、DDoSなどに対する防御を導入できる。
ただし、Managed Rulesは万能ではない。
アプリケーションの仕様を知らないままBlockすると、正常な業務通信を止める可能性がある。
そのため、初期導入ではCountで観測するのだ。
現在のAWS Managed Rules一覧
以下は、AWS公式ドキュメントに掲載されているAWS Managed Rulesの整理なのだ。
WCUは変更される可能性がある。
導入前には、AWS WAFコンソール、ListAvailableManagedRuleGroups、DescribeManagedRuleGroupで確認する。
Baseline rule groups
| Rule Group | VendorName | Name | WCU | 用途 |
|---|---|---|---|---|
| Core rule set | AWS | AWSManagedRulesCommonRuleSet | 700 | OWASP Top 10を含む一般的なWeb攻撃、異常リクエスト対策 |
| Admin protection | AWS | AWSManagedRulesAdminProtectionRuleSet | 100 | 管理画面や管理用パスへの外部アクセス対策 |
| Known bad inputs | AWS | AWSManagedRulesKnownBadInputsRuleSet | 200 | 既知の悪性入力、脆弱性探索、攻撃パターン対策 |
Use-case specific rule groups
| Rule Group | VendorName | Name | WCU | 用途 |
|---|---|---|---|---|
| SQL database | AWS | AWSManagedRulesSQLiRuleSet | 200 | SQLインジェクション対策 |
| Linux operating system | AWS | AWSManagedRulesLinuxRuleSet | 200 | Linux固有のLFI、コマンド実行、ファイル参照系攻撃対策 |
| POSIX operating system | AWS | AWSManagedRulesUnixRuleSet | 100 | POSIX系OSのLFI、パストラバーサル、シェルコマンド系攻撃対策 |
| Windows operating system | AWS | AWSManagedRulesWindowsRuleSet | 200 | Windows、PowerShell、Windows固有パスなどへの攻撃対策 |
| PHP application | AWS | AWSManagedRulesPHPRuleSet | 100 | PHP関数悪用、PHPアプリケーション固有の攻撃対策 |
| WordPress application | AWS | AWSManagedRulesWordPressRuleSet | 100 | WordPress本体、管理パス、既知のWordPress攻撃対策 |
IP reputation rule groups
| Rule Group | VendorName | Name | WCU | 用途 |
|---|---|---|---|---|
| Amazon IP reputation list | AWS | AWSManagedRulesAmazonIpReputationList | 25 | Amazonの脅威インテリジェンスに基づく悪性IP対策 |
| Anonymous IP list | AWS | AWSManagedRulesAnonymousIpList | 50 | Tor、VPN、プロキシ、ホスティング事業者IPなどの匿名化通信対策 |
Intelligent threat mitigation rule groups
| Rule Group | VendorName | Name | WCU | 用途 | 注意 |
|---|---|---|---|---|---|
| Bot Control | AWS | AWSManagedRulesBotControlRuleSet | 50 | Bot分類、スクレイピング、悪性Bot、Targeted Bot対策 | 追加料金あり |
| Fraud Control account takeover prevention | AWS | AWSManagedRulesATPRuleSet | 50 | ログイン試行、漏えい認証情報、アカウント乗っ取り対策 | 追加料金あり。ログインエンドポイント設定が必要 |
| Fraud Control account creation fraud prevention | AWS | AWSManagedRulesACFPRuleSet | 50 | 不正なアカウント作成、量産登録、漏えい認証情報対策 | 追加料金あり。登録エンドポイント設定が必要 |
| Anti-DDoS | AWS | AWSManagedRulesAntiDDoSRuleSet | 50 | DDoS参加リクエストの検知、Challenge、ラベル付け | 追加料金あり |
マネージドルールの選定フロー
Managed Rulesは、全部入れるものではない。
アプリケーションの特性に合わせて選ぶのだ。
実務上の選定順は次の通りなのだ。
- まずBaselineを検討する。
- 次にアプリケーション技術に応じたUse-case specificを選ぶ。
- 外部公開サービスならIP reputationを検討する。
- Botや不正ログインが課題ならIntelligent threat mitigationを検討する。
- WCUと費用を確認する。
- Countで導入する。
まず検討する基本セット
一般的な外部公開Webアプリケーションなら、最初の候補は次なのだ。
| 優先度 | Rule Group | 理由 |
|---|---|---|
| 高 | AWSManagedRulesCommonRuleSet | 一般的なWeb攻撃を広く見るため |
| 高 | AWSManagedRulesKnownBadInputsRuleSet | 明らかに悪性の入力を拾うため |
| 中 | AWSManagedRulesSQLiRuleSet | SQLを使うアプリでは重要なため |
| 中 | AWSManagedRulesAmazonIpReputationList | 悪性IPや探索元を減らすため |
| 中 | AWSManagedRulesAnonymousIpList | 匿名化通信やホスティング元からの攻撃を減らすため |
この構成のWCUは次の通りなのだ。
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesAmazonIpReputationList | 25 |
AWSManagedRulesAnonymousIpList | 50 |
| 合計 | 1,175 |
この構成は、初期導入のたたき台として使いやすい。
ただし、必ずCountで始めるのだ。
技術スタック別の追加候補
アプリケーションの技術スタックが分かっている場合は、次を追加候補にする。
| 条件 | 追加候補 |
|---|---|
| Linux上で動作している | AWSManagedRulesLinuxRuleSet |
| POSIX系OS全般を想定する | AWSManagedRulesUnixRuleSet |
| Windows ServerやIISを使う | AWSManagedRulesWindowsRuleSet |
| PHPを使う | AWSManagedRulesPHPRuleSet |
| WordPressを使う | AWSManagedRulesWordPressRuleSet |
| ログイン機能が重要 | AWSManagedRulesATPRuleSet |
| 会員登録が重要 | AWSManagedRulesACFPRuleSet |
| Botやスクレイピングが課題 | AWSManagedRulesBotControlRuleSet |
| DDoS対策をWAFでも強化したい | AWSManagedRulesAntiDDoSRuleSet |
WordPressの場合は、単体ではなく次の組み合わせを検討するのだ。
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesPHPRuleSet | 100 |
AWSManagedRulesWordPressRuleSet | 100 |
AWSManagedRulesAmazonIpReputationList | 25 |
| 合計 | 1,325 |
WCUの考え方
WCUは、Web ACL capacity unitの略なのだ。
AWS WAFがWeb ACL内のルールを評価するための容量である。
WCUは通信量ではない。
WCUはルール数そのものでもない。
Web ACLにはWCU上限がある。
現在のAWS WAFでは、Web ACLの最大WCUは公式ドキュメント上で5,000 WCUとして説明されているのだ。
ただし、アカウント、リージョン、機能、時期によって制約や表示が変わる可能性がある。
導入前には必ず実際のコンソールまたはAPIで確認するのだ。
WCU計算の基本
WCU計算は単純なのだ。
Web ACLに追加するRule GroupとカスタムルールのWCUを合算する。
例は次の通りである。
| 構成 | WCU |
|---|---|
| CommonRuleSet | 700 |
| KnownBadInputsRuleSet | 200 |
| SQLiRuleSet | 200 |
| AmazonIpReputationList | 25 |
| AnonymousIpList | 50 |
| カスタムIP allow rule | 1 |
| カスタムrate-based rule | 2以上 |
| 合計 | 1,178以上 |
scope-down statementを追加すると、その条件分のWCUが加算される場合がある。
label match ruleを追加した場合も、追加ルール分のWCUが必要なのだ。
したがって、Managed Rulesの合計だけでなく、例外制御用の余力も残す。
WCU設計の目安
WCUは、上限いっぱいまで詰め込まない方がよいのだ。
理由は3つある。
- 誤検知調整用のカスタムルールを追加するため。
- label matchによる後続制御を追加するため。
- 将来のManaged Rules追加やバージョン変更に備えるため。
目安は次の通りなのだ。
| 状態 | 判断 |
|---|---|
| 1,500 WCU未満 | 余裕が大きい |
| 1,500から3,000 WCU | 標準的な構成なら扱いやすい |
| 3,000から4,500 WCU | 追加ルールの余力を意識する |
| 4,500 WCU超 | ルール分割、Web ACL分離、設計見直しを検討する |
構成例
一般的なWebアプリ
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesAmazonIpReputationList | 25 |
AWSManagedRulesAnonymousIpList | 50 |
| 合計 | 1,175 |
まずはこの構成をCountで導入するのだ。
管理画面を持つWebアプリ
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesAdminProtectionRuleSet | 100 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesAmazonIpReputationList | 25 |
| 合計 | 1,225 |
管理画面のパスが正規に外部公開されている場合は、Admin protectionの誤検知に注意するのだ。
WordPress
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesPHPRuleSet | 100 |
AWSManagedRulesWordPressRuleSet | 100 |
AWSManagedRulesAmazonIpReputationList | 25 |
| 合計 | 1,325 |
WordPressでは、プラグインや管理画面の仕様による誤検知を確認するのだ。
ログイン不正対策を重視するWebアプリ
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesATPRuleSet | 50 |
AWSManagedRulesAmazonIpReputationList | 25 |
| 合計 | 1,175 |
ATPはログインエンドポイントの設定が必要なのだ。
CloudFrontではレスポンス検査も考慮する。
会員登録不正を重視するWebアプリ
| Rule Group | WCU |
|---|---|
AWSManagedRulesCommonRuleSet | 700 |
AWSManagedRulesKnownBadInputsRuleSet | 200 |
AWSManagedRulesSQLiRuleSet | 200 |
AWSManagedRulesACFPRuleSet | 50 |
AWSManagedRulesAmazonIpReputationList | 25 |
| 合計 | 1,175 |
ACFPは登録ページとアカウント作成エンドポイントの設定が必要なのだ。
Countモードでのチューニング全体像
Countモードでのチューニングは、次の流れで進めるのだ。
最初に見るべきものは、全量アクセスログではない。
見るべきものは、Countされたリクエストなのだ。
Countで確認する観点
Countされたリクエストは、次の観点で確認する。
| 観点 | 確認内容 |
|---|---|
| Rule Group | どのManaged Rule Groupに一致したか |
| Rule name | どの個別ルールに一致したか |
| Action | Count、Block、Captcha、Challengeなど |
| terminatingRuleId | 最終的にどのルールが効いたか |
| labels | 後続のlabel matchで使えるか |
| URI | 特定画面やAPIに偏っているか |
| HTTP method | GET、POST、PUT、DELETEなどが想定どおりか |
| query string | 業務上あり得る値か |
| request body | 入力フォーム、JSON、XML、GraphQLなどの仕様に合うか |
| headers | User-Agent、Content-Type、X-Forwarded-Forなどが想定どおりか |
| source IP | 一般利用者、社内、監視、Bot、攻撃元のどれに近いか |
| country | 想定利用地域と合っているか |
| user agent | ブラウザ、Bot、監視、スキャナのどれに近いか |
| frequency | 単発か、継続的か、大量発生か |
| business event | ログイン、検索、申込、決済、アップロードなど重要操作か |
sampled requestsは初期確認に便利なのだ。
ただし、sampled requestsは全件ではない。
最終判断にはAWS WAFログを使う。
誤検知の分類
Countされたリクエストは、次のように分類するのだ。
| 分類 | 判断 | 対応 |
|---|---|---|
| 明らかな攻撃 | 業務上あり得ない文字列、探索、スキャン | Block候補 |
| 正常通信 | 業務機能として必要 | 例外化候補 |
| 監視通信 | 外形監視、脆弱性診断、社内監視 | 送信元やパスで条件付き許可 |
| Bot通信 | 検索エンジン、提携先、スクレイパー | Bot種別ごとに判断 |
| 判断保留 | 仕様確認が必要 | Count継続 |
| 高リスクだが必要 | 業務上必要だが攻撃にも似る | scope-down、label match、追加認証、レート制限を検討 |
誤検知が見つかった場合でも、Rule Group全体を無効化するのは避けます。
まずは個別ルール単位で調整します。
ビジネスロジックが不確かな場合の確認ポイント
WAFログだけでは、正常通信か攻撃かを判断できないことがあります。
その場合は、Blockへ移す前に次を確認します。
| 確認ポイント | 内容 |
|---|---|
| 画面・APIの用途 | そのURIが何の業務機能か |
| 利用者 | 一般顧客、社内利用者、管理者、外部連携先のどれか |
| 入力仕様 | 特殊文字、HTML、SQL風文字列、JSON、XMLを許容するか |
| 入力長 | 長文、Base64、ファイル名、URL、スクリプト断片を許容するか |
| Content-Type | application/json、multipart/form-data、text/plainなどが仕様どおりか |
| 認証状態 | 未認証、ログイン済み、管理者権限のどれか |
| 業務影響 | Blockした場合に申込、決済、ログイン、登録が止まるか |
| 代替経路 | WAFで止めてもアプリ側で安全に処理できるか |
| アプリ側検証 | サーバ側で入力検証、認可、CSRF対策、SQL対策があるか |
| 監視・診断 | 社内監視、外形監視、脆弱性診断の通信ではないか |
| 過去実績 | 過去にも同じ入力が正常に使われていたか |
| 件数傾向 | 少数の正常利用か、大量の機械的通信か |
| 失敗率 | 対象リクエストがアプリ側で成功しているか失敗しているか |
| 利用時間帯 | 営業時間、バッチ時間、キャンペーン期間に偏るか |
| 問い合わせ | 利用者問い合わせや業務部門からの申告があるか |
この確認が取れない場合、原則として即Blockにはしません。
まずCount継続にします。
次に、影響範囲を絞った例外または段階的Blockを検討します。
Blockへ移してよい目安
次の条件を満たすほど、Blockへ移しやすくなります。
| 条件 | 判断 |
|---|---|
| 一定期間、正常通信への一致がない | Blockへ移しやすい |
| 一致内容が明らかに攻撃 | Blockへ移しやすい |
| アプリ担当者が業務上不要と確認した | Blockへ移しやすい |
| 対象URIが公開不要な管理系パス | Blockへ移しやすい |
| 同一送信元から大量発生している | Block、rate limit、Challengeを検討 |
| 誤検知が特定パスだけ | 例外化後にBlock |
| 誤検知が広範囲 | Count継続または設計見直し |
| 業務仕様が不明 | Count継続 |
| 決済、申込、ログインに関係する | 追加確認後に段階移行 |
観測期間は、システムの利用サイクルに合わせます。
最低でも、平日と休日を含めます。
月次処理、給与日、請求日、キャンペーン、繁忙期がある場合は、その期間も確認します。
個別ルールをCountに残す
Managed Rule Groupの中で、一部のルールだけが誤検知を起こすことがあります。
この場合は、該当ルールだけをCountに残します。
他のルールはBlockへ移せます。
例です。
| 状況 | 悪い対応 | 良い対応 |
|---|---|---|
| CommonRuleSetの一部だけ誤検知 | CommonRuleSet全体を外す | 該当個別ルールだけCount継続 |
| SQLiRuleSetが検索画面で誤検知 | SQLiRuleSet全体を外す | 検索画面だけscope-downで調整 |
| AnonymousIpListが社内VPNを検知 | AnonymousIpList全体を外す | 社内IPだけ条件付き許可 |
| WordPress管理画面で誤検知 | WordPressRuleSet全体を外す | 管理者IP、認証状態、URIで限定調整 |
scope-down statementの使い方
scope-down statementは、Managed Rule Groupの評価対象を絞るために使います。
使いどころは次です。
| 用途 | 例 |
|---|---|
| 特定パスだけ対象にする | /loginだけATP対象 |
| 特定パスだけ対象外にする | /api/searchだけSQLi誤検知を回避 |
| 特定メソッドだけ対象にする | POSTだけ検査 |
| 特定Content-Typeだけ対象にする | JSON APIだけ検査 |
| 特定IPを除外する | 社内監視IPだけ除外 |
| 特定Hostだけ対象にする | 管理用サブドメインだけAdmin protection対象 |
除外範囲は狭くします。
広い除外は、防御効果を大きく削ります。
label matchの使い方
AWS Managed Rulesは、リクエストにlabelを付与します。
label matchを使うと、Managed Rulesの検知結果を後続ルールで再利用できます。
使い方の例です。
| 用途 | 例 |
|---|---|
| 検知だけ先に行う | Managed Rule GroupをCountにしてlabelを見る |
| 後続でBlockする | 特定labelかつ特定URIだけBlock |
| 後続でChallengeする | Bot系labelにChallengeを適用 |
| 例外を細かく作る | 特定labelかつ社内IP以外をBlock |
| 誤検知を避ける | 特定labelでも正規APIだけ許可 |
label matchは柔軟です。
ただし、条件が複雑になりやすいです。
設定理由を必ず記録します。
本番移行の進め方
CountからBlockへ移すときは、影響が小さいものから進めます。
- 明らかな攻撃だけをBlockにする。
- 正常通信への一致がないルールをBlockにする。
- 誤検知がある個別ルールはCountに残す。
- scope-down statementで対象を絞る。
- label matchで後続制御する。
- 重要機能の4xx増加を監視する。
- 問い合わせや業務影響を確認する。
- 問題があれば該当ルールだけCountへ戻す。
本番移行では、戻し方を事前に決めます。
WAFのBlock化は、アプリケーション変更と同じように変更管理します。
よくある失敗
Rule Group全体を外す
一部のルールで誤検知が出ただけなのに、Rule Group全体を外すケースがあります。
防御範囲を大きく落とします。
個別ルールのCount化を先に検討します。
sampled requestsだけで判断する
sampled requestsは全件ではありません。
傾向を見るには便利です。
最終判断にはログを使います。
例外条件を広くしすぎる
パス全体、IP全体、Host全体を広く除外すると、防御対象が薄くなります。
URI、メソッド、IP、ヘッダ、labelを組み合わせて狭くします。
Countのまま放置する
Countは観測のための状態です。
恒久的にCountのままにすると、防御にはなりません。
定期的に棚卸しします。
ビジネス仕様を確認せずBlockする
WAFログだけでは正常通信か判断できない場合があります。
ログイン、申込、決済、会員登録、検索、ファイルアップロードは特に慎重に扱います。
運用で記録すべきこと
最低限、次を記録します。
| 項目 | 内容 |
|---|---|
| 日付 | 変更した日 |
| 対象Web ACL | どのWeb ACLを変更したか |
| 対象Rule Group | どのManaged Rule Groupを変更したか |
| 対象個別ルール | どの個別ルールをCount継続またはBlockにしたか |
| 変更内容 | Count、Block、Challenge、Captcha、例外条件など |
| 理由 | 誤検知、攻撃確認、業務要件など |
| 根拠ログ | 判断に使ったログ、メトリクス、sampled requests |
| 業務確認 | 誰に何を確認したか |
| WCU影響 | 追加・削除後のWCU |
| 戻し方 | 問題発生時に戻す設定 |
Managed RulesはAWS側で更新されます。
そのため、過去の判断理由を残すことが重要です。
実務チェックリスト
導入前
- 保護対象のCloudFront、ALB、API Gateway、AppSyncなどを確認した。
- Web ACLのscopeを確認した。
- アプリケーションの主要機能を確認した。
- ログイン、申込、決済、検索、アップロードの有無を確認した。
- 技術スタックを確認した。
- 必要なManaged Rulesを選定した。
- WCUを計算した。
- 追加料金が発生するRule Groupを確認した。
- ログ出力先を決めた。
Count期間中
- Countイベントをルール別に集計した。
- CountイベントをURI別に集計した。
- Countイベントを送信元別に集計した。
- 重要機能への一致を確認した。
- 誤検知候補を分類した。
- アプリ担当者に仕様確認した。
- 監視通信や診断通信を識別した。
- 個別ルールのCount継続を設定した。
- scope-down statementを検討した。
- label matchを検討した。
Block移行前
- 正常通信への一致がないことを確認した。
- 業務上必要な入力ではないことを確認した。
- 重要機能への影響がないことを確認した。
- 例外条件が最小範囲であることを確認した。
- 4xx増加を監視できることを確認した。
- 問い合わせ増加を検知できることを確認した。
- ロールバック手順を決めた。
- 変更記録を残した。
出典
- AWS Managed Rules rule groups list
- AWS Managed Rules for AWS WAF
- Baseline rule groups
- Use-case specific rule groups
- IP reputation rule groups
- AWS WAF Bot Control rule group
- AWS WAF Fraud Control account takeover prevention rule group
- AWS WAF Fraud Control account creation fraud prevention rule group
- AWS WAF Distributed Denial of Service prevention rule group
- Testing and tuning your AWS WAF protections
- Preparing for testing your AWS WAF protections
- Monitoring and tuning your AWS WAF protections
- Overriding rule group actions in AWS WAF
- Enabling your protections in production
まとめ
AWS WAFのチューニングは、ルールを大量に読む作業ではない。
保護対象の業務仕様を整理し、必要なManaged Rulesを選び、WCUを計算し、Countで実通信を観測する作業なのだ。
誤検知があれば、Rule Group全体を外すのではなく、個別ルール、scope-down statement、label matchで最小範囲に調整する。
ビジネスロジックが不確かな場合は、業務仕様、入力仕様、認証状態、重要機能への影響、アプリ側検証、過去実績を確認する。
確認が取れないものは、原則としてCount継続にする。
問題ないものから段階的にBlockへ移す。
この進め方なら、業務影響を抑えながらAWS WAFの防御効果を高められるのだ。