特定のWordPress記事だけ「501 Not Implemented」になった話|Xserver WAFの誤検知とMarsEditで抜けた経緯

特定のWordPress記事だけ「501 Not Implemented」になった話|Xserver WAFの誤検知とMarsEditで抜けた経緯 WordPress
この記事は約16分で読めます。

ある日、書きためていた WordPress 関連の技術記事を更新しようとしたら、突然 501 Not Implemented が表示されました。

最初は「あ、また WordPress 本体かプラグインの不具合かな」と思ってブラウザを再読み込みしたんですが、何度試しても結果は同じ。Xserver 上の WordPress で、特定の記事の更新ボタンを押した瞬間だけ 501 が出るようになっていたんです。

Xserverで501 Not Implementedエラーが表示された画面

厄介だったのは「ある記事だけ」というところでした。ブログ全体が落ちているわけでも、WordPress 全体が壊れているわけでもない。コードやコマンド例を多めに含んだ特定の記事だけが、更新ボタンを押した瞬間に 501 を返してくる。何度試しても再現する。

最終的にたどり着いた答えは、Xserver の WAF が記事本文中のコードやコマンド例を「攻撃パターンっぽい」と判断していた、というものでした。本文そのものが攻撃だったわけではなく、ただの技術解説なのですが、WAF は「これはブログ記事の説明文です」と文脈まで読んでくれるわけではありません。

この記事は、その日の試行錯誤と、原因を切り分けた手順、そして再発を減らすために変えた運用をまとめたものです。同じ症状で詰まっている方の参考になれば、と思って書きました。

検証環境:WordPress 6.9.4 / Xserver スタンダードプラン / PHP 8.3.21 / MarsEdit 5.3.12(確認時期:2026年3月)

この記事の前提

ここで書いている内容は、私の運用環境で起きた 501 エラーを切り分けた記録です。Xserver の仕様や WAF ルールは変更される可能性があります。実際に作業する場合は、現在の Xserver 公式マニュアルやサーバーパネルの表示も確認してください。

症状はとにかく分かりにくかった

当時の症状は、ぱっと見だと何が起きているのか掴みにくいものでした。

WordPress の管理画面には入れます。記事の編集画面も開きます。本文の入力もできます。でも、更新ボタンを押した瞬間に 501 Not Implemented が表示される。プラグインの保存も、設定変更もできるのに、特定の記事の更新だけがダメ。

501エラー発生の流れ図

しかも全記事ではありません。テキスト中心の記事は普通に更新できる。一方で、コマンド例や設定ファイル名、PHP コードを多く含む特定の記事だけが失敗する。ここまで挙動が偏っていると、「WordPress 全体が壊れている」というより、「送信している記事本文の中身そのものが、どこかで止められている」と考えるしかなくなります。

ややこしかったのが、画面に出るのが「501 Not Implemented」だったことです。

HTTP の 501 は、本来はサーバーがリクエストに必要な機能へ対応していないとき、たとえば認識できないリクエストメソッドを受け取ったときなどに使われるステータスです。

ただ、こちらは管理画面から普通に記事を更新しているだけ。特殊な HTTP メソッドを投げているわけではありません。「こちらが変なリクエストを送った」と考えるより、途中のセキュリティ判定で止められた可能性を疑う方が、状況的には自然でした。

WAF を疑うまでに遠回りしたこと

正直に書いておくと、最初から「これは WAF だ」と分かったわけではありません。WAF にたどり着くまでには、けっこう遠回りしました。

最初に疑ったのは、いつもの順番です。WordPress 本体を最新版にしてみる。プラグインを順番に無効化してみる。「最近入れたあのプラグインが悪さをしているのかも」と思って一つずつ無効化を試したのですが、症状は変わりませんでした。

次に試したのは、環境側の問題という線です。普段使っているブラウザの拡張機能やキャッシュ、Cookie が悪さをしている可能性もあるので、別のブラウザ、シークレットウィンドウ、別の端末から同じ記事の更新を試しました。

結果はどれも同じです。同じ記事の更新ボタンを押すと、同じように 501 が返ってくる。

ここまで来て、ようやく「クライアント側ではなく、サーバー側で何かが止めている」という線に絞り込めました。WordPress 本体でもプラグインでもブラウザでも端末でもないなら、残るのはサーバー側の判定処理です。そこから WAF を疑い始めた、というのが正確な流れになります。

最初の 501 から原因を WAF と特定するまでは、だいたい半日〜1 日くらいでした。比較的早く片付いた方だとは思いますが、その日のうちは「何が起きているのか分からない」という時間がそれなりにあった、というのが体感です。

Xserver サーバーパネルで確認したこと

WAF を疑い始めてから最初にやったのは、Xserver サーバーパネルの WAF 設定を眺めることでした。

Xserverサーバーパネルの「WAF設定」画面

Xserver の WAF には、複数の項目があります。Xserver 公式マニュアルでも、WAF 設定として XSS 対策、SQL 対策、ファイル対策、メール対策、コマンド対策、PHP 対策などの項目が案内されています。

このうち、私が特に気にしたのは コマンド対策 でした。詰まった記事には、ターミナルのコマンド例や、シェルで使う記号がそれなりに混ざっていたからです。

項目名 記事内で引っかかりそうな内容
XSS対策 scriptタグ、JavaScriptのイベント属性、Cookie操作の説明など
SQL対策 SELECT、INSERT、DELETE、UNIONなどのSQL例
ファイル対策 .htaccess、wp-config.php、php.iniなどの設定ファイル名
メール対策 to、cc、bcc、mail() などのメール関連文字列
コマンド対策 ls、curl、wget、ssh、rm、パイプ、セミコロンなど
PHP対策 exec()、shell_exec()、file_get_contents() などの関数名

技術ブログでは、これらの文字列を普通に使います。サーバー作業の記事なら lscurl は出てきますし、WordPress の設定記事なら wp-config.php.htaccess もよく出てきます。攻撃コードを書いているつもりはなくても、WAF から見ると「危険な文字列を含む POST 送信」に見える可能性があります。

ここが、技術記事と WAF の相性が悪くなるところです。

切り分けの実験を3つやってみた

WAF を疑ったあと、原因をもう少し絞るために小さな実験を 3 つしました。いきなり WAF を全部 OFF にするのは怖かったので、ステップごとに変化を見ています。

501エラー切り分けフローチャート

1 つ目は、コードをほとんど含まない別の記事を更新してみることでした。こちらは問題なく通ります。これで、WordPress 全体やサーバー全体が落ちているわけではない、と確認できました。

2 つ目は、問題の記事の本文を短くして、コードブロックやコマンド例を一時的に削ってから更新する、というやり方です。すると、更新できる場合がありました。本文中のどこかに WAF が反応している可能性が、ここでかなり高くなりました。

3 つ目は、Xserver サーバーパネルから WAF 設定を開き、コマンド対策だけを一時的に OFF にして、元のままの記事を更新してみました。私の環境では、ここで記事更新が通るようになりました。少なくともこのケースでは、コマンド対策が反応していた可能性が高い、というところまで絞れました。

注意:WAF 設定は、変更してすぐに反映されないことがあります。Xserver の案内でも、設定反映に時間がかかる場合があります。変更直後に試して「変わらない」と判断せず、少し時間を置いてから確認した方が安全です。

WAFを一時OFFにするときに気をつけたこと

WAF を OFF にすれば記事が更新できるとしても、常時 OFF のまま運用するのはおすすめできません。WAF はサイトを守るための仕組みです。誤検知があるからといって全部切ったままにすると、本来止めるべき攻撃まで通してしまう可能性があります。

私が実際にやった手順は、こんな感じです。

手順 内容
1 Xserver のサーバーパネルで WAF 設定を開く
2 まずは「コマンド対策」だけを一時的に OFF にする
3 反映を待つ
4 シークレットウィンドウなどで記事を更新する
5 更新できたら、すぐに WAF を ON に戻す

このとき、全項目をまとめて OFF にするのは避けました。原因の切り分けにもなりませんし、防御を広く外すことになるからです。

作業中は、不要なプラグイン操作やテーマ編集も同時にやらないようにしました。複数の変更を一度にやると、あとで何が原因だったのか分からなくなります。

記事本文で引っかかりやすかった文字列

実際に技術記事を書いていると、WAF に疑われやすい文字列はかなり身近なところにあります。

サーバー作業の記事なら lscurl は普通に出てきます。WordPress の設定記事なら wp-config.php.htaccess もよく使います。PHP の記事なら file_get_contents()exec() に触れることもあります。

分類 記事で使いがちな文字列
シェルコマンド cd ls rm mv cp curl wget ssh
記号 | ; &&
設定ファイル .htaccess .htpasswd php.ini wp-config.php
PHP関数 exec() shell_exec() session_start() file_get_contents()
JavaScript <script> javascript: onerror document.cookie
SQL SELECT INSERT UPDATE DELETE UNION

ただし、ここに挙げた文字列を使ったら必ず 501 になる、という意味ではありません。実際には、前後の文字列や送信内容、サーバー側の判定によって変わります。

私の体感では、短いコマンド名や記号がまとまって出てくる記事ほど、更新時に引っかかりやすい印象でした。

再発を減らすためにコードの載せ方を変えた

その場しのぎで WAF を一時 OFF にするだけだと、次に似た記事を書くたびに同じ問題が起きます。

そこで、長いコードやコマンドを本文にそのまま大量に載せる運用を見直すことにしました。

長いコードは GitHub Gist や添付ファイルに逃がす

長いサンプルコードは、記事本文にすべて貼るのではなく、GitHub Gist や GitHub リポジトリに置くようにしました。

記事内では、コードの要点や変更箇所を説明し、完全なコードは外部に置きます。本文に危険判定されそうな文字列を大量に含めずに済みますし、読者にとっても、長いコードを記事中で延々と読むより、必要な人だけ外部リンクで確認できる方が見やすい場合があります。

設定例はスクリーンショットと短い抜粋を併用する

設定ファイルやコマンドの説明では、スクリーンショットを使う方法もあります。

ただし、画像だけにすると読者がコピーできません。私は「画像で全体像を見せる」「本文では必要最小限の抜粋だけ載せる」という併用が使いやすいと感じました。

危険なコマンドは完成形のままにしない

セキュリティ上、破壊的なコマンドや攻撃に使えるコードを、そのまま完成形で載せるのは避けた方がいいです。これは WAF 対策というより、技術ブログとしての責任に近い部分です。

たとえば、危険なコマンドは「こういう操作は危険です」と概念で説明し、実行可能な形でそのまま置かない。複数コマンドをセミコロンでつなげたワンライナーは、1 行ずつ分けて説明する。書き方を変えるだけでも、読みやすさと安全性の両方が上がります。

もう一つの抜け道:MarsEdit 経由なら通った

切り分けで原因がだいぶ絞れたところで、ふと思いついたのが、普段から併用している MarsEdit でした。

長い記事を書くときは MarsEdit、ちょっとした修正は管理画面、という使い分けが私の普段の運用です。だから今回も、駄目元で「MarsEdit からだったら通るかな」と試してみたくらいの気持ちでした。本文も投稿先のサーバーも同じなのだから、エディタを変えたところで結果は変わらないだろう、と内心では思っていました。

ところが、MarsEdit のパブリッシュボタンを押したら、そのまま通ったんです。

正直、最初は信じられませんでした。本文は同じ。サーバーも同じ。WordPress 本体も同じ。違いは「どのアプリから送るか」だけ。それで 501 が出たり通ったりするのか、と。

  • WordPress 管理画面から更新 → 501 エラー
  • MarsEdit から投稿 → そのまま通った

MarsEditのWordPress投稿画面

MarsEdit経由で公開できた記事の表示

何度試しても結果は同じでした。WordPress 管理画面の更新ボタンで 501、MarsEdit のパブリッシュボタンで成功。これが繰り返し再現できる以上、通信経路の違いが効いている、と認めるしかありませんでした。

なぜ MarsEdit なら通るのか

少し踏み込んで考えてみると、こういうことだと思います。

左:WordPress管理画面 → REST API/admin-ajax → JSON/form-urlencoded → WAF検査 → 詰まる、右:MarsEdit → xmlrpc.php → XML本文 → WAF判定をすり抜ける、という経路の違いを並べた図解

WordPress 管理画面からの記事更新は、内部的には REST API(あるいは admin-ajax)に対する POST リクエストになります。本文は JSON や form-urlencoded の形でサーバーに送られるため、WAF はこれを「通常の Web フォーム送信」として扱い、ボディの中身を文字列レベルで検査しやすい状態です。

一方、MarsEdit は古くからの xmlrpc.php 経由で投稿します。本文は XML 形式でシリアライズされて送られるため、WAF が同じルールセットで検査していたとしても、エンコードの差や経路の違いで文字列マッチが効かなかった可能性があります。あくまで私の推測の範囲ではありますが、「同じ内容なのに通る・通らないが分かれた」事実から逆算すると、ここに差があったと考えるのが自然でした。

もちろん、これは私の環境での結果です。すべての Xserver 環境で MarsEdit なら必ず通る、と一般化できる話ではありません。

それでも、技術記事を書く人にとって、投稿経路をもう 1 本持っておくのはかなり安心です。管理画面の更新ボタンを押すたびに 501 が出る状態は、精神的にもなかなかきついものがあります。

SetappにMarsEditが含まれている画面

XML-RPC を開けるなら、入口はちゃんと絞っておく

MarsEdit を投稿の保険として使うことにすると、必然的に xmlrpc.php を有効にしておくことになります。

XML-RPC は便利ですが、何も考えずに開けっぱなしにするのは少し不安があります。そこで、Xserver の WordPress セキュリティ設定で、XML-RPC API アクセス制限とホワイトリストを確認しました。

私の運用では、投稿に使う IP アドレスをホワイトリストに登録し、不要なアクセスをできるだけ減らす形にしました。

XserverのWordPressセキュリティ設定 XML-RPCホワイトリスト

ただし、自宅回線でもルーターの再起動などで IP アドレスが変わることがあります。ホワイトリスト運用は、投稿する場所や回線がある程度固定されている人向けです。外出先や複数拠点から投稿する場合は、毎回 IP を確認する必要があります。

アプリケーションパスワードが使えないとき

MarsEdit で WordPress に接続する場合、できればアプリケーションパスワードを使いたいところです。

ただ、セキュリティ系プラグインの設定によっては、アプリケーションパスワードが無効化されていることがあります。私の環境でも、このあたりの設定を確認する必要がありました。

もしアプリケーションパスワードが使えない場合は、MarsEdit 専用の WordPress ユーザーを作り、権限を必要最小限にする方法があります。

  • MarsEdit 専用ユーザーを作る
  • 権限は必要最小限にする
  • 強固なランダムパスワードを使う
  • XML-RPC は IP 制限で入口を絞る

投稿用の入口を増やす以上、便利さだけでなく守り方も一緒に考えておいた方が安心です。

MarsEditの設定画面

MarsEdit でも投稿できないとき

MarsEdit を使っても投稿できない場合に、私が見るのはこのあたりです。

確認項目 見るところ
IP ホワイトリスト 現在の IP アドレスと登録済み IP が一致しているか
XML-RPC 制限 Xserver 側で XML-RPC がブロックされていないか
セキュリティプラグイン Wordfence などが XML-RPC やアプリケーションパスワードを止めていないか
ユーザー権限 下書き保存や公開に必要な権限があるか
CDN やプロキシ Cloudflare などを使っている場合、アクセス元 IP の見え方が変わっていないか

とくに IP ホワイトリストは見落としやすいです。昨日まで投稿できていたのに急に失敗する場合、回線側の IP が変わっていることがあります。

WAF でも MarsEdit でも直らないときに見るところ

WAF 設定を見直しても直らない場合、WAF 以外の原因も考えます。

私なら、まず WordPress 側のエラーログを確認します。PHP エラーが出ているなら、プラグインやテーマの問題かもしれません。

wp-config.php でデバッグログを有効にする場合は、こんな書き方になります。

/wp-content/debug.log にエラーが出ていないのに、更新時だけ 501 になる場合は、WordPress の内部処理まで届く前に止められている可能性があります。一方で、debug.log に PHP エラーがはっきり残っている場合は、WAF ではなく、プラグインやテーマの処理を疑った方がよいです。

Xserver サポートに相談するなら、書き方が大事

自分で切り分けても解決できない場合は、Xserver サポートへ相談した方が早いです。

そのときは、「501 が出ます」だけではなく、発生条件と試したことを具体的に書くと伝わりやすくなります。私が実際に書いた問い合わせ文の構成は、こんな形でした。

発生日時はできるだけ具体的に書いた方がよいです。サポート側でログを確認しやすくなります。

振り返り:今回の対応で見えてきたこと

今回の 501 エラーで分かったのは、技術ブログでは「正しい記事を書いているだけ」でも、サーバー側のセキュリティ機能に止められることがある、ということでした。

とくに、WordPress、PHP、サーバー設定、コマンドラインの記事を書いている場合、本文中の文字列が WAF に誤検知される可能性があります。

公開→501遭遇→WP/プラグイン更新→別ブラウザ→サーバー側を疑う→WAF設定確認→コード削除実験→コマンド対策OFFで通る→MarsEdit発見→XML-RPC運用、という流れを1枚にまとめたタイムライン図解

私の環境では、3 つの対応が現実的に効きました。

対応 内容
一時対応 WAF の該当項目だけを一時的に OFF にして、更新後すぐ ON に戻す
再発防止 長いコードは GitHub Gist や添付ファイルへ移す
投稿経路の保険 MarsEdit など、管理画面以外の投稿経路を用意する

もちろん、WAF を OFF にするのは最終手段に近い扱いです。常時 OFF ではなく、必要なときだけ、範囲を絞って、作業後すぐ戻す。ここはかなり大事です。

同じトラブルが起きたときのチェックリスト

最後に、同じ問題が起きたときに私が見る項目をまとめておきます。

501 エラーが出た直後に確認すること

順番 確認内容
1 別の記事は更新できるか
2 問題の記事からコード部分を減らすと更新できるか
3 WAF のどの項目が関係していそうか
4 コマンド対策だけを一時的に OFF にすると、挙動が変わるか
5 WordPress の debug.log に PHP エラーが残っていないか
6 更新後、WAF を ON に戻したか

今後の運用で気をつけること

項目 運用
長いコード GitHub Gist やリポジトリに置く
危険なコマンド 完成形をそのまま載せすぎない
設定ファイル 必要な部分だけ抜粋する
投稿経路 管理画面以外の投稿手段も用意する
XML-RPC 使う場合は IP 制限などで入口を絞る
サポート相談 発生日時と試したことを具体的に残す

最後に

WordPress でコード付きの記事を更新したときに 501 Not Implemented が出ると、最初はかなり焦ります。

ただ、私の環境では、WordPress 本体の故障ではなく、Xserver の WAF が記事本文中のコードやコマンド例に反応していた可能性が高い状況でした。特定の記事だけ更新できない、コード部分を削ると通る、WAF のコマンド対策を一時的に OFF にすると更新できる。ここまで揃うなら、WAF の誤検知をかなり強く疑ってよいと思います。

そして、もう一つの抜け道として MarsEdit のような XML-RPC 経由の投稿クライアントがある、というのも、知っておくと精神的にだいぶ楽です。

WAF を切りっぱなしにするのは危険です。必要なときだけ一時的に OFF にして、更新後すぐ ON に戻す。長いコードは外部に逃がす。MarsEdit のような別の投稿経路も用意しておく。このあたりを整えておくと、技術記事を書くたびに「また 501 が出るかも」と怖がらずに済むようになります。

関連記事

コメント

タイトルとURLをコピーしました