2026年8月20日
2026年8月20日
AWS WAFでWebアプリを保護する方法|Web ACLの作成・マネージドルール・レート制限とWordPressの誤検知対策
AWS WAF は、CloudFront や ALB(Application Load Balancer)の手前でリクエストを検査し、攻撃とみられる通信を遮断するサービスです。保護を始めるには、Web ACL を作って守りたいリソースに関連付け、AWS が提供するマネージドルールとレート制限ルールを「カウント」モードで試し、ログで誤検知が無いことを確かめてから「ブロック」に切り替える、という順番で進めます。この記事では、その手順と、WordPress で起きやすい誤検知への対処を説明します。
AWS WAF のコンソールは近年画面構成が見直されており、Web ACL の呼び方や設定画面の並びがバージョンによって異なることがあります(2026年10月現在)。ここでは機能の目的で説明するので、項目名は目安として読み、迷ったら公式ドキュメントを確認してください。
AWS WAF の仕組みを先に押さえる
AWS WAF の設定は、次の3つの要素でできています。
- Web ACL:ルールの入れ物です。ルールを上から順に評価し、どのルールにも当てはまらないリクエストには既定のアクション(通常は「許可」)を適用します。
- ルール:「この条件に当てはまったら、ブロック・許可・カウント・CAPTCHA などのどれを行うか」を定義します。条件には IP アドレス、国、URI、ヘッダー、本文の文字列、リクエストの頻度などが使えます。
- ルールグループ:複数のルールをまとめたものです。AWS や AWS Marketplace の販売者が保守する「マネージドルールグループ」と、自分で作るルールグループがあります。
Web ACL を関連付けられる主なリソースは、CloudFront ディストリビューション、ALB、API Gateway の REST API、AppSync、Cognito のユーザープールなどです。EC2 インスタンスに直接は関連付けられないため、EC2 だけで WordPress を公開している場合は、前段に ALB か CloudFront を置く構成にする必要があります。
CloudFront 用は「グローバル」で作る
CloudFront に関連付ける Web ACL は、リージョンではなく CloudFront(グローバル)の範囲で作成します。CLI や Terraform で扱う場合は、米国東部(バージニア北部、us-east-1)を指定します。東京リージョンで作った Web ACL は CloudFront の選択肢に出てこないので、ここが最初のつまずきどころです。ALB に関連付ける場合は、ALB と同じリージョンで作ります。
ステップ1:Web ACL を作り、マネージドルールを追加する
コンソールで Web ACL の作成を始め、範囲(CloudFront かリージョン)と関連付けるリソースを選びます。次に、AWS のマネージドルールグループから基本となるものを追加します。WordPress サイトで候補になるのは次のグループです。
- Core rule set(AWSManagedRulesCommonRuleSet):OWASP Top 10 で挙げられるような一般的な攻撃パターンを幅広く検査します。
- Known bad inputs(AWSManagedRulesKnownBadInputsRuleSet):既知の脆弱性を突くリクエストのパターンを検査します。
- SQL database(AWSManagedRulesSQLiRuleSet):SQL インジェクションのパターンを検査します。
- PHP application / WordPress application:PHP や WordPress に特有の攻撃パターンを検査します。
- Amazon IP reputation list:攻撃元として知られる IP アドレスからの通信を検査します。
ボット対策(Bot Control)やアカウント乗っ取り対策のように、別料金がかかる高度なマネージドルールグループもあります。料金体系は変わるため、ここでは金額に触れませんが、追加する前に料金ページで確認してください。
Web ACL にはルールの複雑さに応じて消費する処理容量(WCU)の単位があり、既定の範囲を超えると追加の料金がかかる場合があります。
最初はすべてカウントで動かす
マネージドルールは、いきなりブロックで有効にすると、正常な操作まで止めてしまうことがあります。追加するときにルールグループ全体のアクションを「カウント」に上書きし、数日から1週間ほど本番の通信を流して、どのルールに何が当たるかを観察してから、ブロックへ切り替えるのが安全です。
ステップ2:WordPress のログイン画面にレート制限を掛ける
wp-login.php や xmlrpc.php への総当たり攻撃は、WordPress で最も多い攻撃の一つです。レートベースのルールを使うと、同じ IP アドレスから一定時間内に一定回数を超えたリクエストを自動で止められます。次は、wp-login.php へのリクエストを5分間あたり100回で制限するルールの JSON の例です(最初はカウントで動かす想定です)。
{
"Name": "rate-limit-wp-login",
"Priority": 10,
"Statement": {
"RateBasedStatement": {
"Limit": 100,
"EvaluationWindowSec": 300,
"AggregateKeyType": "IP",
"ScopeDownStatement": {
"ByteMatchStatement": {
"SearchString": "/wp-login.php",
"FieldToMatch": { "UriPath": {} },
"TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }],
"PositionalConstraint": "ENDS_WITH"
}
}
}
},
"Action": { "Count": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "rate-limit-wp-login"
}
}
制限値は、自社の利用者がログインする頻度を見て決めます。同じ事業所から多くの人が同じグローバル IP で接続する環境では、低すぎる値だと正当な利用者が止まります。評価期間や設定できる下限値は過去に変更されているため、最新の値は公式ドキュメントで確認してください。
xmlrpc.php は、Jetpack や一部のアプリ連携で使われていなければ、レート制限ではなくブロックしてしまう方法もあります。止める前に、使っている連携サービスが xmlrpc.php に依存していないかを確認します。
CloudFront の後ろの ALB で使う場合の注意
CloudFront を経由して ALB に届くリクエストの送信元 IP は、CloudFront のものになります。この状態で ALB 側の Web ACL にレート制限を掛けると、多数の利用者をまとめて止めてしまいます。CloudFront を使うなら Web ACL も CloudFront に関連付けるのが基本です。どうしても ALB 側で判定する場合は、X-Forwarded-For ヘッダーの IP で集計する設定(転送 IP の設定)を使いますが、ヘッダーは偽装できるため、ALB を CloudFront 以外から直接叩けないようにしておくことが前提になります。
ステップ3:ログを有効にして誤検知を調べる
Web ACL のログは、CloudWatch Logs、S3、Amazon Data Firehose のいずれかに送れます。送信先の名前は aws-waf-logs- で始める決まりがあるので、ロググループやバケットを先に作るときに注意します。ログには、どのルールが判定したか、どの値に当たったかが記録されるため、カウント中の観察に欠かせません。
コンソールのサンプルリクエストでも直近の判定の一部は見られますが、全件ではないので調査にはログを使います。
WordPress で起きやすい誤検知と対処
カウントで観察していると、WordPress では次のような誤検知がよく見つかります。
- 投稿の保存や画像のアップロードが止まる:Core rule set には、リクエスト本文の大きさを制限するルール(SizeRestrictions_BODY)が含まれています。ブロックエディターで長い記事を保存したり、メディアをアップロードしたりすると、これに当たることがあります。
- 記事の本文に HTML やスクリプト風の文字列があると止まる:コードを紹介する記事や埋め込みタグを含む記事で、クロスサイトスクリプティングの検査に当たることがあります。
- 管理画面の Ajax や REST API が止まる:admin-ajax.php や /wp-json/ への正当なリクエストが、本文やクエリの検査に当たる場合があります。
対処の基本は、当たったルールだけをカウントに上書きし、そのうえで範囲を絞った自前のルールで補うことです。ルールグループ全体を無効にすると、ほかの検査まで失われます。次は、Core rule set のうち本文サイズのルールだけをカウントにする設定の例です。
{
"Name": "AWS-AWSManagedRulesCommonRuleSet",
"Priority": 20,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet",
"RuleActionOverrides": [
{ "Name": "SizeRestrictions_BODY", "ActionToUse": { "Count": {} } }
]
}
},
"OverrideAction": { "None": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesCommonRuleSet"
}
}
そのうえで、例えば管理画面からの大きな本文は、管理者の接続元 IP に限って許可する、といったルールを組み合わせます。管理画面へのアクセス元を IP セットで絞れる環境なら、/wp-admin/ と wp-login.php を特定の IP 以外ブロックする方法は効果が大きく、誤検知の調整もしやすくなります。ただし、admin-ajax.php は訪問者向けの機能でも使われることがあるため、まとめてブロックしないよう注意します。
切り替え後の確認と運用
ブロックに切り替えたら、次の点を確認します。
- 管理画面へのログイン、投稿の保存、メディアのアップロード、問い合わせフォームの送信が正常に動く
- CloudWatch のメトリクスで、ブロック数が急に増えていない
- 外部の監視サービスや決済などの連携先からの通知が止まっていない
WAF はアプリの脆弱性を直すものではなく、攻撃の一部を手前で減らす仕組みです。WordPress 本体やプラグインの更新、不要なプラグインの削除、強いパスワードと多要素認証と組み合わせて使います。AWS Shield Standard は CloudFront や ALB に自動で適用される DDoS 対策ですが、アプリ層の攻撃への備えは WAF のルールで行う、という役割分担も覚えておくと設計しやすくなります。
まとめ
- AWS WAF は Web ACL を CloudFront や ALB に関連付けて使います。CloudFront 用はグローバル(us-east-1)で作成します。
- Core rule set、Known bad inputs、SQL database、WordPress application などのマネージドルールを基本に、wp-login.php へのレート制限を加えます。
- 最初はカウントで動かし、ログで誤検知を確認してからブロックに切り替えます。
- WordPress では本文サイズや XSS の検査で投稿の保存が止まることがあるため、当たったルールだけを上書きし、範囲を絞ったルールで補います。
- WAF は更新や認証の強化の代わりにはならないので、他の対策と組み合わせて運用します。