2013年に作ったままのWordPressサイト「イノベーションの軸」(wonder9.com)が、PHPの更新をきっかけにまったく表示されなくなりました。記事も画像も失わず、その日のうちに最新のWordPress 7.1.3で復旧させた経緯をまとめます。
きっかけ:WordPressとPHPに相次いだ重大な脆弱性
2026年の秋は、WordPressで動くサイトにとって厳しい季節でした。数週間のうちに、WordPress本体と、それを動かすPHPの両方に、外部からサーバーを乗っ取られかねない脆弱性が見つかったからです。
| 公開 | 対象 | 内容 | 対策 |
|---|---|---|---|
| 2026年10月21日 | PHP(通称 PHP2shell、CVE-2026-109618 / 109619) | 外部から任意のコードを実行されるおそれ。CVSS 9.2。IPAがパッチ公開前に注意喚起 | PHPの修正版(セキュリティパッチ)を適用 |
| 2026年9月22日 | WordPress本体 4.7.0〜7.1.1(CVE-2026-87902) | ログイン不要でサーバー内のPHPファイルを読み込ませられる。条件がそろうとコード実行。CVSS 9.2 | WordPress 7.1.2 以降、または各系列の修正版へ更新 |
このサイトを預けているお名前.com レンタルサーバー「共用サーバーSD」では、10月22日にPHPの脆弱性への対応が告知され、ファイルマネージャーとWebメールが一時停止されました。10月23日には、PHP 7.4と8.4へのセキュリティパッチ適用が完了したと発表されています。PHP 7.3以下は緩和策のみで、7.4以上への変更が推奨されました。
これを受けてサイトのPHPを 8.4 に切り替えたところ、wonder9.com はまったく開かなくなりました。
13年放置していたサイトの姿
サイトは2013年にお名前.comの共用サーバーSDで立ち上げ、コントロールパネルの「WordPressインストール」(かんたんブログインストール)で入れたものです。その後はごくたまに更新しただけで、中身はほぼ当時のままでした。調べてみると、ひとつのデータベースに2つのWordPressが同居していました。
| 場所 | WordPress | テーブル名の頭 | 中身 |
|---|---|---|---|
| www.wonder9.com(本体) | 4.9.26 | wp_ | 固定ページ6、投稿33、画像10。テーマは Twenty Twelve |
| www.wonder9.com/stuff(スタッフ用) | 3.5.2 | wp2_ | 固定ページ2(うち1つは初期のサンプル) |
ほかにも、当時の資料(MaenoLab.pdf、27MB)や、記事一覧を出すためにページの中にPHPを直接書く「Exec-PHP」という古いプラグインが使われていました。コメント6件は、すべて承認待ちのままたまったスパムでした。
2013年のWordPressとプラグインは、2026年の脆弱性への修正が届かないどころか、今のPHPでは動かないものばかりでした。「動いているから大丈夫」ではなく、「古いまま動いていること自体が危険」な状態だったわけです。
なぜ表示されなくなったのか
WordPressは PHP というプログラミング言語の上で動いています。PHPは版が上がるたびに古い書き方を廃止するので、2013年に書かれたプログラムは新しいPHPでは動きません。

壊れたのは「古いプログラム×新しいPHP」という組み合わせだけです。記事や設定が入ったデータベースはどの場合も無事だったので、プログラム側を最新に入れ替えるだけで復旧できました。
救出の進め方
方針は「まず控えを取る、本番に触る前に手元で試す」の2つだけです。デザインは変えてもよいと決めていましたが、結果的には新しいサーバーを用意するのではなく、同じサーバーの同じ場所でプログラムだけを入れ替える方法を選びました。

1〜3で取った控えがあるので、どの段階でも元に戻せます。5では古いフォルダを消さずに名前を変えておき、表示されなければ戻せるようにしました。データベースはサーバー上のものをそのまま使い、wp-admin/upgrade.php で最新の形に更新しています。スパムコメントの削除や、PHPを書いていたページの置き換えは、初回のアクセスで1回だけ動く小さなプログラムに任せました。
作業の実際とつまずいたところ
今回は AI(Claude)と相談しながら進めました。Claude がブラウザでコントロールパネルやサイトの状態を確かめ、私がFTPでファイルを出し入れする、という分担です。
管理者でログインしないと何も見えない
お名前.comのコントロールパネル(cp.rentalserver.jp)に、最初はメールアドレスのアカウントで入っていました。この権限では「PHPバージョン変更」「MySQL」「FTPアカウント」がすべて押せません。サーバーの管理者アカウントで入り直して、ようやく中身を確認できました。
FileZilla がウイルス対策に止められた
FTPソフトの定番 FileZilla を入れようとしたところ、Windows が「望ましくない可能性のあるソフトウェア」として停止しました。標準の配布物に広告ソフトが同梱されていたためです。広告同梱のない WinSCP に切り替え、サイトのファイル一式(約144MB、6,064ファイル)を手元にダウンロードしました。
phpMyAdmin がない中でのデータベースの書き出し
共用サーバーSDのMySQLはサーバー内部からしか接続できず、コントロールパネルにも書き出し機能が見当たりませんでした。そこで、書き出し専用の小さなPHPファイルを一時的に置き、ブラウザから1回だけ実行して、全データを .sql ファイル(約1.2MB)として受け取りました。接続先は wp-config.php から読み取り、推測されにくい合言葉がないと動かないようにして、使い終わったらすぐ削除しています。
「元に戻す」応急処置は効かなかった
途中でPHPを 7.4 に戻してみましたが、「このページは動作していません」のままでした。WordPress本体だけでなく、2013年頃のプラグインも動かなかったためです。PHPを古くするのではなく、WordPressを新しくするのが正解でした。
古いフォルダが消えない
入れ替え後、退避した古いフォルダ(wp-old)をWinSCPで削除すると、中身は消えたのにフォルダだけが「ディレクトリではありません」と残りました。FTPでは、中身を先にすべて消してからフォルダを消すので、このようなことが起きるようです。古いプログラムそのものはすべて削除できています。
技術解説:SQLでデータベースを書き出し、中身を確かめる
WordPressの記事や設定は、すべてMySQLのテーブルに入っています。画面が壊れても、テーブルさえ無事ならサイトは取り戻せます。今回使ったSQLを、仕組みが分かる程度に紹介します。
1. 書き出し:3つのSQLをテーブルごとに繰り返す
書き出し用のPHPがやっているのは、次の繰り返しだけです(要点だけを書き直したもので、接続情報や合言葉の部分は省いています)。
$db->set_charset('utf8'); // 保存時と同じ文字コードで読む
echo "SET NAMES utf8;\nSET FOREIGN_KEY_CHECKS=0;\n";
$tables = $db->query('SHOW TABLES'); // (1) テーブルの一覧
while ($t = $tables->fetch_row()) {
$name = $t[0];
$c = $db->query("SHOW CREATE TABLE `$name`")->fetch_row(); // (2) 設計図
echo "DROP TABLE IF EXISTS `$name`;\n" . $c[1] . ";\n";
$r = $db->query("SELECT * FROM `$name`", MYSQLI_USE_RESULT); // (3) 中身
while ($row = $r->fetch_row()) {
$v = array_map(fn($x) => $x === null ? 'NULL'
: "'" . $db->real_escape_string($x) . "'", $row);
echo "INSERT INTO `$name` VALUES (" . implode(',', $v) . ");\n";
}
}
- SHOW TABLES:データベース内のテーブル名を全部取ります。今回は wp_ が12個、wp2_ が11個の計23個でした。
- SHOW CREATE TABLE:テーブルを作り直すための CREATE TABLE 文をサーバー自身に書いてもらいます。列の型や索引がそのまま写せます。
- SELECT * → INSERT:1行ずつ読んで INSERT 文に置き換えます。real_escape_string は、本文中の ‘ や改行が SQL を壊さないようにエスケープする役目です。
- MYSQLI_USE_RESULT:結果をメモリに貯め込まず、流しながら出力します。共用サーバーの小さなメモリでも大きなテーブルを扱えます。
- SET NAMES utf8 / FOREIGN_KEY_CHECKS=0:読み戻すときに文字化けや順番待ちのエラーが起きないように、先頭で宣言しておきます。
出来上がった .sql は、こんな形のテキストです。最後の行に入れておいた「END OF DUMP」があるのを確認して、途中で切れていないことを確かめました。
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `wp_posts`;
CREATE TABLE `wp_posts` ( `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT, ... );
INSERT INTO `wp_posts` VALUES ('1','1','2013-07-01 02:02:13', ... );
...
-- END OF DUMP
2. 手元のMySQLに読み込んで、中身を数える
.sql を作業用のMySQL(MariaDB)に読み込み、何がどれだけあるかを数えました。WordPressは記事も固定ページも画像も、すべて wp_posts の1行として持ち、post_type 列で種類を分けています。
SELECT post_type, post_status, COUNT(*)
FROM wp_posts
GROUP BY post_type, post_status;
| post_type | post_status | 件数 | 意味 |
|---|---|---|---|
| post | publish | 33 | 公開中の投稿 |
| page | publish | 6 | 公開中の固定ページ |
| attachment | inherit | 10 | 画像などの添付ファイル |
| nav_menu_item | publish | 6 | メニューの項目 |
| revision | inherit | 213 | 編集履歴(移行時に削除) |
| post | auto-draft | 1 | 自動保存の下書き(削除) |
サイトの場所や使っているテーマ、有効なプラグインは wp_options に入っています。siteurl が /wp、home が / になっていて、「プログラムは /wp フォルダ、公開アドレスはトップ」という構成だと分かりました。入れ替えを「同じ場所で」行えばよいと判断できたのは、この2行のおかげです。
SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('siteurl', 'home', 'template', 'active_plugins');
3. 新しいPHPで動かない記事を探す
Exec-PHP は本文に PHP のコードを直接書かせるプラグインです。これを外すと、コードがそのまま画面に出てしまいます。本文に「<?php」を含む記事を探すと、「グローバル社会の政治経済キーワード30」の1ページだけでした。このページは WordPress 標準の「最新の投稿」ブロック(カテゴリー指定・30件・古い順)に置き換えています。
SELECT ID, post_title
FROM wp_posts
WHERE post_status = 'publish'
AND post_content LIKE '%<?php%';
4. 日本語が壊れていないかをバイトで確かめる
最初に結果を表示したとき、サイト名が「?????????」と出てひやりとしました。文字化けがデータそのものの問題か、表示側の問題かは、中身をバイト列で見れば分かります。
SELECT option_value, HEX(LEFT(option_value, 6))
FROM wp_options
WHERE option_name = 'blogname';
-- 結果:イノベーションの軸 | E382A4E3838EE38399E383BCE382B7E383A7
E382A4 は UTF-8 の「イ」、E3838E は「ノ」です。データは正しく、画面に出すときの文字コード指定が抜けていただけだと分かりました。
5. 古いデータベースを最新の形へ
WordPressはデータベースの形の版を wp_options の db_version で管理しています。今回は 38590(WordPress 4.9 系)から 61833(WordPress 7.1 系)へ一気に上げました。本番では wp-admin/upgrade.php を開くだけで、必要な ALTER TABLE などを WordPress が順に実行してくれます。事前に手元のコピーで同じ更新を試し、全ページが表示できることを確かめてから本番に臨んでいます。
復旧の結果
入れ替え後、www.wonder9.com は PHP 8.4 上の WordPress 7.1.3 で正常に表示され、記事・固定ページ・画像・PDF はすべてそのまま残りました。
| 項目 | 作業前 | 作業後 |
|---|---|---|
| 表示 | 「このページは動作していません」 | 正常に表示 |
| PHP | 8.4(サイトが対応できず) | 8.4(お名前.comのセキュリティパッチ適用済み) |
| WordPress 本体 | 4.9.26 と 3.5.2 | 7.1.3(CVE-2026-87902 修正済み) |
| テーマ | Twenty Twelve(古い版) | Twenty Twelve(最新版、見た目はそのまま) |
| プラグイン | Jetpack、Exec-PHP など5個(2013年頃の版) | WP Multibyte Patch、Akismet のみ |
| コメント | スパム6件 | 0件 |
| /stuff サイト | WordPress 3.5 のまま、英語のエラーを表示 | 中身を本体の /re-start/ へ移し、残りはトップへ転送 |

デザインはまず従来と同じ Twenty Twelve で立ち上げました。管理画面でテーマを切り替えれば、最新の Twenty Twenty-Five のような見た目にもできます。

これからの保守と脆弱性対策
今回いちばんの教訓は、「放置した年数だけ、直すのが大変になる」ということです。13年分の差は一気に埋められましたが、次は差をためない仕組みにします。
定期的にやること
| いつ | やること | どこで |
|---|---|---|
| 自動 | WordPress 本体のセキュリティ更新(標準で有効)。プラグインとテーマも自動更新にする | 管理画面の「プラグイン」「外観>テーマ」で「自動更新を有効化」 |
| 毎月 | 管理画面にログインし、更新が溜まっていないか、サイトヘルスに警告がないかを見る | 「ダッシュボード>更新」「ツール>サイトヘルス」 |
| 毎月 | お名前.comのお知らせと障害・メンテナンス情報を確認する | コントロールパネルのホーム画面 |
| 毎月と大きな更新の前 | データベースと wp-content(特に uploads)を手元にバックアップする | バックアップ用プラグイン、または WinSCP |
| 注意喚起が出たとき | WordPress や PHP の重大な脆弱性が報じられたら、その週のうちに更新を確認する | IPA・JPCERT/CC の注意喚起、お名前.comのお知らせ |
| PHP の切り替え時 | 先にバックアップ、切り替え後に全ページを開いて確認する。一度捨てた古い版には戻せないことがある | コントロールパネル「PHPバージョン変更」 |
| 毎年 | 使っていないプラグイン・テーマ・ユーザーを整理し、ドメインとサーバーの契約も確認する | 管理画面、お名前.com Navi |
攻撃されにくくするための考え方
- 入れるものを減らす:プラグインもテーマも、入っているだけで攻撃の入口になります。今回は5個あったプラグインを2個に減らしました。
- 作業用のファイルを残さない:データベース書き出し用のスクリプトや古い WordPress のフォルダは、使い終わったらすぐ消します。
- ログインを守る:管理者は長く推測されにくいパスワードにし、二段階認証も検討します。使っていないアカウントは削除します。
- サーバーの守りも使う:共用サーバーSDのコントロールパネルには「WAF設定」があります。不正なリクエストをサーバーの手前で止める仕組みです。
- バックアップがあれば怖くない:今回落ち着いて作業できたのは、最初にファイルとデータベースを手元に確保したからです。
このサイトの保守方針
- 更新はできるかぎり自動にし、月に1回は管理画面で状態を確かめる
- 使わないプラグイン・テーマ・作業用のファイルは、サーバーに置かない
- 大きな変更の前には、必ずデータベースとファイルの控えを取る
- WordPress 側だけでなく、サーバー側の防御機能も併せて使う
- 管理者アカウントは、強いパスワードと必要最小限の人数で守る
- これからは定期的に記事も更新し、「放置しないサイト」にする