2024-04-10 に WordPress を更新したあと、ModSecurity が WordPress の正常な通信をブロックする事象が発生しました。当時の WordPress は 6.5.2 で、更新直後は問題が見えにくく、Redis などのキャッシュの影響で発現が遅れた可能性もあります。
この記事では、WordPress 更新後に WAF が正常通信を止める状況を、単なる「誤検知」として片付けず、偽陽性、真陽性、偽陰性、真陰性の判定分類と、ModSecurity の運用調整として整理します。
結論として、WAF を丸ごと無効化するのではなく、audit log を見て、URI、パラメータ、rule id、検知内容を確認し、必要最小限の例外にすることが重要です。
書籍
ModSecurity Handbook, Second Edition
ModSecurity と Web Application Firewall の設定、ログ、ルール、チューニングを確認したい場合の参考書籍です。英語書籍であり、価格や在庫はリンク先で確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
書籍
WordPress 仕事の現場でサッと使える!デザイン教科書 [WordPress 6.x対応版] 改訂第3版
WordPress のサイト構築、テーマ、カスタマイズ、運用項目を確認したい場合の参考書籍です。価格や在庫、WordPress の最新仕様との差分はリンク先や公式ドキュメントで確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
関連する記事
WordPress の REST API と WAF の関係、Apache での ModSecurity 導入、WordPress 構築と Kubernetes 運用の記事と合わせて読むと、この問題の位置づけが分かりやすくなります。
- WordPress の「返答が正しい JSON レスポンスではありません」を切り分ける
- Ubuntu 22.04 Apache WAF – ModSecurity と OWASP CRS の導入と誤検知調整
- Ubuntu 22.04 WordPress – Apache / PHP / MariaDB で CMS を構築する
- WordPress を Kubernetes で運用する構成
発生したこと
WordPress 更新後、管理画面や REST API の一部の通信が ModSecurity によりブロックされました。WordPress の更新により、リクエスト本文、パラメータ、API の挙動、管理画面側の通信内容が変わると、既存の WAF ルールに引っかかることがあります。
このような状況では、「WordPress が壊れた」「WAF がバグった」と早合点しない方がよいです。WAF は入力された通信をルールに基づいて評価しているだけであり、その判定が運用対象の正常通信と衝突した状態として見る必要があります。
誤検知という表現への違和感
セキュリティシステムが正常な通信をブロックしたとき、「誤検知」という表現がよく使われます。ただ、この言葉は WAF 側の単純なバグのように受け取られやすく、切り分けを雑にする危険があります。
もちろん、本当にルールや実装に問題がある場合もあります。しかし運用者としては、まず「どの通信が、どのルールで、なぜ攻撃に見えたのか」を確認すべきです。その上で、正常通信を許可するための調整を行います。
WAF 判定の 4 分類
WAF の判定は、正当な通信か不正な通信か、通過させたかブロックしたかで整理できます。
| 判定 | 正当な通信 | 不正な通信 |
|---|---|---|
| 通過 | 真陰性 (true negative)。正常な通信を正しく通過させた状態。 | 偽陰性 (false negative)。不正な通信を見逃した状態。 |
| ブロック | 偽陽性 (false positive)。正常な通信を不正と判定して止めた状態。 | 真陽性 (true positive)。不正な通信を正しく止めた状態。 |
システムとして望ましいのは、正当な通信を通し、不正な通信を止めることです。つまり、真陰性と真陽性を維持することです。
運用上目立ちやすいのは偽陽性です。正常な画面操作や API 呼び出しが止まるため、すぐ利用者影響になります。一方で、偽陰性は見えにくく、攻撃を通してしまうため、より危険です。WAF 調整では、偽陽性を消すために偽陰性を増やさないことが重要です。
WordPress 更新後に WAF が反応しやすい理由
WordPress は本体、ブロックエディタ、REST API、プラグイン、テーマが組み合わさって動きます。更新によって通信内容が変わると、WAF から見たリクエストの特徴も変わります。
- ブロックエディタの保存内容が REST API 経由で送信される。
- HTML、CSS、JavaScript、JSON 断片を含む本文が POST される。
- プラグインやテーマにより追加パラメータが増える。
- 管理画面の API エンドポイントやリクエスト形式が変わる。
- キャッシュにより更新直後ではなく少し遅れて影響が見えることがある。
WAF はアプリケーションの意図を完全には理解しません。通信の文字列、構造、パラメータ、スコアに基づいて判断します。そのため、WordPress 側では正常な投稿内容でも、WAF のルールからは攻撃パターンに見えることがあります。
まず audit log を確認する
ModSecurity で重要なのは、ブロックされたという結果だけではなく、どのルールで何が検知されたかです。audit log を確認し、対象の URI、rule id、メッセージ、パラメータを見ます。
sudo tail -n 300 /var/log/apache2/modsec_audit.log
sudo grep -n "wp-json" /var/log/apache2/modsec_audit.log
sudo grep -E 'Message:|id "[0-9]+"|uri|Matched Data' /var/log/apache2/modsec_audit.logログを見るときは、攻撃らしい文字列だけに注目するのではなく、その通信が WordPress のどの操作に対応しているのかを確認します。記事保存、画像アップロード、プラグイン更新、ログイン、コメント投稿では、許容すべき範囲が異なります。
切り分け手順
WAF が疑わしい場合でも、いきなり WAF を恒久的に無効化しない方がよいです。まず、WAF を一時的に切り分け、同時に WordPress、PHP、リバースプロキシのログも確認します。
| 確認項目 | 見ること |
|---|---|
| HTTP ステータス | 403 なのか、500 なのか、JSON ではない HTML 応答なのか。 |
| WAF ログ | rule id、検知メッセージ、対象 URI、対象パラメータ。 |
| WordPress 操作 | 記事保存、REST API、プラグイン更新、画像アップロードなど、どの操作か。 |
| PHP ログ | WAF ではなく PHP エラーで JSON が壊れていないか。 |
| プロキシログ | リバースプロキシやロードバランサーでブロックされていないか。 |
curl -i https://www.example.com/wp-json/
curl -i https://www.example.com/wp-json/wp/v2/posts?per_page=1
sudo tail -n 100 /var/log/apache2/error.log
sudo tail -n 100 /var/log/apache2/access.log例外は狭く作る
偽陽性が確認できた場合でも、WAF 全体を無効化したり、WordPress 全体を無条件に除外したりするのは避けます。例外は、URI、ルール ID、パラメータ、メソッドなどでできるだけ狭くします。
- 対象 rule id を確認してから除外する。
- WordPress 全体ではなく、必要な URI に限定する。
- 全パラメータではなく、問題になったパラメータに限定する。
- 管理画面、REST API、公開フォームを同じ扱いにしない。
- 調整後も audit log を見て、想定外の通過が増えていないか確認する。
WAF 例外は、便利な穴ではなく、運用上必要な通信を通すための管理対象です。後から見直せるように、なぜその例外が必要なのかを設定ファイルや運用メモに残すべきです。
DetectionOnly で観察する選択肢
更新直後や大きな変更の前後では、一時的に DetectionOnly で観察する方法もあります。これはブロックせずに検知だけを見るため、本番影響を抑えながら新しい通信パターンを確認できます。
ただし DetectionOnly は防御を弱める状態です。常用する設定ではなく、変更前後の観察や調整期間に限定して使うべきです。
sudo grep '^SecRuleEngine' /etc/modsecurity/modsecurity.conf
sudo sed -i 's/^SecRuleEngine On/SecRuleEngine DetectionOnly/' /etc/modsecurity/modsecurity.conf
sudo apache2ctl configtest
sudo systemctl reload apache2調整が終わったら、意図した例外を設定した上で SecRuleEngine を On に戻します。
sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
sudo apache2ctl configtest
sudo systemctl reload apache2キャッシュも疑う
WordPress 更新直後にすぐ影響が見えない場合、Redis、ページキャッシュ、ブラウザキャッシュ、リバースプロキシのキャッシュが関係していることがあります。
WAF の問題に見えても、実際には古い JavaScript や古い API 応答が残り、管理画面の挙動が不安定に見えることもあります。WAF ログとキャッシュの状態を分けて確認します。
まとめ
WordPress 更新後に ModSecurity が正常な通信をブロックすることはあります。このとき重要なのは、「誤検知だから WAF が悪い」と決めつけることではなく、偽陽性として正しく分類し、どのルールがどの通信を止めたのかを確認することです。
WAF は運用しなければ価値が出ません。WordPress のように REST API、管理画面、プラグイン、テーマが頻繁に変わるアプリケーションでは、更新後に WAF の audit log を確認し、必要な範囲だけ調整する運用が前提になります。
WAF を丸ごと無効化すれば問題は消えますが、防御も消えます。運用者としては、正常通信を通し、不正通信を止めるために、偽陽性を狭く潰しながら偽陰性を増やさないことが大切です。


