手当たり次第に書くんだ

飽きっぽいのは本能

WordPress 更新後に ModSecurity が反応する理由 – WAF の偽陽性と例外設計を見る

WordPress を更新した後に、管理画面の保存、プラグイン更新、REST API、Gutenberg の操作が WAF / ModSecurity に止められることがあります。画面上では保存エラーや JSON レスポンスエラーに見えても、実際には WAF がリクエスト本文を攻撃パターンとして判定している場合があります。

この記事では、WordPress 更新後に ModSecurity が反応する理由と、例外をどのように狭く作るべきかを整理します。単に WAF を止めるのではなく、何がどのルールに反応したのかを見て、運用可能な形に調整するのが目的です。

発生すること

WordPress 更新後の WAF 反応は、次のような症状として見えます。

  • ブロックエディタで記事を保存できない
  • REST API が 403 になる
  • プラグイン更新や設定保存が失敗する
  • 管理画面上では JSON レスポンスエラーに見える
  • 本文内のコード、URL、HTML、SQL 風文字列にだけ反応する

WordPress 側の画面だけを見ると原因が分かりにくいですが、WAF の audit log を見ると、どのルールがどのパラメータに反応したのかを確認できます。

誤検知という表現への違和感

WAF の反応をすぐに「誤検知」と呼ぶのは、少し雑です。WAF はリクエスト本文に含まれるパターンを見て判定しているため、技術記事のコードブロックやコマンド例が攻撃パターンに似ていれば、ルールとしては反応します。

問題は、反応したこと自体よりも、その反応をどう運用に落とすかです。WordPress の正当な操作を止め続けるなら調整が必要ですが、だからといって WAF 全体を無効化すると、本来守りたい範囲まで失います。

WAF 判定の 4 分類

WAF のログを見る時は、反応を大きく 4 つに分けると整理しやすくなります。

分類内容対応
正しい検知実際に攻撃や不正アクセスを止めている遮断を維持する
許容できる検知管理者操作だが頻度が低く、手動許可でよい都度確認する
調整すべき検知正当な WordPress 操作を継続的に止める狭い例外を作る
過剰な除外広く除外しすぎて保護が弱くなる例外範囲を見直す

WordPress 更新後に反応しやすい理由

WordPress 更新後は、REST API の使われ方、Gutenberg の保存内容、プラグインのリクエスト形式、管理画面の JavaScript の挙動が変わることがあります。結果として、以前は通っていたリクエストが WAF ルールに当たるようになることがあります。

  • Gutenberg が記事本文を REST API で送る
  • コードブロックや HTML ブロックがリクエスト本文に入る
  • プラグイン設定に URL、正規表現、SQL 風の文字列が入る
  • REST API の endpoint や request body が更新で変わる
  • OWASP CRS の更新で判定が厳しくなる

特に技術ブログでは、記事本文にシェルコマンド、設定ファイル、SQL、HTML、HTTP ヘッダーが含まれるため、一般的なブログより WAF に反応しやすい面があります。

まず audit log を確認する

最初に見るべきなのは audit log です。エラー画面や WordPress の通知だけでは、どのルールが原因か分かりません。

コマンド

grep -i "Access denied" /var/log/apache2/modsec_audit.log
grep -i "wp-json" /var/log/apache2/modsec_audit.log
grep -i "id \" /var/log/apache2/modsec_audit.log

確認したいのは、少なくとも rule idrequest URImatched variablematched data です。これが分からない状態で例外を作ると、範囲が広くなりすぎます。

見るべき項目

項目見る理由
Rule IDどの WAF ルールが反応したかを特定する
Request URI管理画面、REST API、特定プラグインのどこで起きたかを見る
Matched Variable本文、ヘッダー、Cookie、引数のどこに反応したかを見る
Matched Dataどの文字列が攻撃パターンに見えたかを見る
Client IP / User管理者操作か外部アクセスかを切り分ける

たとえば REST API の投稿保存で、記事本文の一部にだけ反応しているなら、REST API 全体を除外するのではなく、そのルールと対象変数に絞って調整するのが基本です。

例外は狭く作る

WAF の例外は、できるだけ狭く作ります。広い例外は一時的には楽ですが、後から何を守っているのか分からなくなります。

避けたい例外望ましい例外
WordPress 全体を WAF から除外する管理画面や REST API の必要な endpoint に限定する
すべての CRS ルールを無効化する反応した rule id に限定する
すべての request body を除外する対象パラメータや matched variable に限定する
恒久例外をすぐ入れる一時的に観察してから恒久化する

例外の考え方

<LocationMatch "^/wp-json/wp/v2/posts">
    SecRuleRemoveById 942140
</LocationMatch>

上記は考え方の例です。実際には、audit log で確認した rule id、対象 URI、対象変数に合わせて調整します。ルール ID だけを見て機械的に除外するのではなく、何に反応しているのかを確認してから適用します。

DetectionOnly で観察する選択肢

本番でいきなり遮断するのが難しい場合は、一時的に DetectionOnly で観察する選択肢もあります。これは検知ログを取りながら遮断しないモードです。

ただし、DetectionOnly は恒久運用の逃げ道ではありません。どのルールがどの正常操作に反応するかを把握し、必要な例外を作るための観察期間として使うのが自然です。

キャッシュや CDN も疑う

WAF 以外にも、リバースプロキシ、キャッシュ、CDN がエラー応答を返していることがあります。WordPress から見ると同じ保存失敗でも、実際には前段のキャッシュやプロキシが POST リクエストを正しく扱っていない場合があります。

  • REST API の POST がキャッシュ対象になっていないか
  • Cookie や Authorization ヘッダーが前段で落ちていないか
  • キャッシュされた 403 や 500 が返っていないか
  • WAF とキャッシュのどちらが先に応答しているか

参考書籍

参考
書籍
参考書籍
ModSecurity Handbook, Second Edition

ModSecurity / WAF のルール、検知、例外設計を深く確認したい場合の参考書籍です。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

関連する記事

まとめ

WordPress 更新後に ModSecurity が反応する場合、まず audit log を確認し、rule id、request URI、matched variable、matched data を見ることが重要です。画面上のエラーだけでは、WAF が原因なのか、PHP やリバースプロキシが原因なのか分かりません。

WAF の反応を単に誤検知として扱うのではなく、正当な管理操作を止めているのか、実際に危険な通信を止めているのかを分けて考えます。

例外はできるだけ狭く作り、WordPress 全体や REST API 全体を広く除外しないことが大切です。WAF を止めるのではなく、WordPress の運用に合わせて検知を調整する。この考え方が、長期運用では一番安全です。

WordPress 更新後に ModSecurity が反応する理由 – WAF の偽陽性と例外設計を見る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る