WordPress障害対応

WordPressで原因不明の403/500:ModSecurityを疑う切り分け手順

「管理画面で保存を押すと403になる」「特定のページだけ500になる」。WordPress本体にもプラグインにも異常がないのに、特定の操作だけが弾かれる。

このパターンで犯人になりやすいのが ModSecurity です。サーバー側のWAF(Web Application Firewall)で、多くの共用レンタルサーバーで既定有効になっています。

WordPressのログには何も残らないため、WordPress側をいくら調べても原因にたどり着きません。

結論:この順で切り分ける

  1. エラーが特定の操作だけか確認する
  2. サーバーのエラーログを見る(WordPressのログではない)
  3. ModSecurityを一時的に無効化して再現しなくなるか確認する
  4. 原因ルールを特定し、そのルールだけ除外する

ModSecurityが疑わしいサイン

以下に当てはまるなら、可能性が高いです。

403が返るのに、WordPressのdebug.logに何もない

WordPressに到達する前にサーバーが弾いているためです。WordPress側のログに残らないのは当然で、これ自体が手がかりになります。

特定の操作だけ失敗する

  • 記事本文にコードを含めて保存すると403
  • 特定の単語を含むフォーム送信だけ失敗
  • ファイルアップロードだけ失敗

ModSecurityは「攻撃っぽいパターン」を弾きます。SQLらしき文字列、<script>../、特定の関数名などが本文に入っていると、正当な投稿でも攻撃と誤判定されます。

「昨日まで動いていた」

ModSecurityのルールセットはサーバー会社が自動更新します。こちらが何もしていなくても、ある日突然弾かれ始めます。

管理者だけ、または特定のIPだけで起きる/起きない

IPレピュテーションによるルールが絡んでいる可能性があります。


STEP 1: 事象を確定する

まず「何をすると何が起きるか」を1文で言えるようにします。

  • どのURLか
  • どの操作か(GET / POST / ファイルアップロード)
  • ステータスコードは何か(403 / 406 / 500)
  • 毎回か、たまにか

403と500では原因が違います。ModSecurityは既定で403を返しますが、設定によっては406や500を返すこともあります。


STEP 2: サーバーのエラーログを見る

WordPressのログではなく、サーバー側のログです。cPanelなら「エラー」または「生アクセスログ」から取得できます。SSHが使えるならログファイルを直接見ます。

ModSecurityが発動していれば、こういう行が出ます。

ModSecurity: Access denied with code 403 (phase 2).
Pattern match "..." at ARGS:content.
[file "/etc/modsecurity/rules/xxx.conf"] [line "123"] [id "941100"]
[msg "XSS Attack Detected"] [severity "CRITICAL"]

この id が原因ルールのIDです。 ここまで取れれば、あとは除外するだけです。

ログが見られない場合は、サーバー会社のサポートに「ModSecurityのログを確認してほしい」と依頼します。日時とURLを添えると早いです。


STEP 3: 一時的に無効化して確認する

原因ルールが特定できない場合、まずModSecurityが犯人かどうかを確定させます。

cPanelには「ModSecurity」の項目があり、ドメイン単位でオン・オフできます。オフにして同じ操作を試し、成功すればModSecurityが原因で確定です。

.htaccess で無効化できるサーバーもあります。

<IfModule mod_security.c>
  SecFilterEngine Off
  SecFilterScanPOST Off
</IfModule>

ただし新しいバージョン(ModSecurity 2.x以降)ではこの書き方は効かず、以下になります。

<IfModule mod_security2.c>
  SecRuleEngine Off
</IfModule>

注意: 無効化は切り分けのためだけに使い、そのまま放置しないでください。 WAFを丸ごと切るのは、防御を全部外すことです。


STEP 4: 原因ルールだけを除外する

ルールIDが分かったら、そのルールだけを無効化します。全体を切るより遥かに安全です。

<IfModule mod_security2.c>
  SecRuleRemoveById 941100
</IfModule>

特定のURLでのみ除外することもできます。

<LocationMatch "/wp-admin/post.php">
  <IfModule mod_security2.c>
    SecRuleRemoveById 941100
  </IfModule>
</LocationMatch>

cPanelの管理画面から、ドメイン単位でルールIDを無効化できるサーバーもあります。.htaccess を触れない環境ではこちらを使います。


除外する前に考えること

ルールを外す前に、なぜそのルールが発動したかを確認してください。

「XSS Attack Detected」が出ているなら、本当にその本文に <script> が入っているのかもしれません。正当な投稿なら除外してよいですが、そもそも不要なタグを入れているなら本文を直すほうが正しい。

除外するルールは最小限に。 「動かないから全部切る」は、後で侵入されたときに理由が説明できなくなります。


ModSecurity以外の可能性

ModSecurityを無効化しても直らない場合、以下を順に見ます。

PHPのmemory_limit / max_input_vars

500エラーで、かつ大きなデータを送ったときだけ起きるなら、PHPの制限です。とくに max_input_vars(既定1000)は、フォーム項目が多いページで簡単に超えます。

// wp-config.php で確認
ini_get('max_input_vars');

mod_evasive / レート制限

短時間に連続アクセスすると弾かれる設定です。自動投稿やAPI連携で起きます。

プラグインのファイアウォール

セキュリティ系プラグインが独自にブロックしていることがあります。ModSecurityと二重にかかっていると、切り分けがさらに難しくなります。プラグイン側のログも確認してください。


まとめ

WordPressのログに何も出ないエラーは、WordPressの外で起きています。

  • サーバー側のログを見る
  • 一時的に無効化して犯人を確定する
  • ルールIDを特定し、それだけを除外する

この順で進めれば、原因不明の403は原因不明でなくなります。


サイトが原因不明のエラーで止まっている方へ

WordPressの障害復旧を承っています。白画面、403/500、管理画面に入れない、更新後に壊れたなど。原因の特定から復旧まで対応します。

販売実績58件・評価5.0・出品者ランク プラチナ(2026-09時点)