2026年10月21日に、PHPに深刻な脆弱性(CVE-2026-109618 / CVE-2026-109619、通称「php2shell」)が見つかり、修正版が公開されました。ログイン不要で、リクエストを送るだけでサーバー上で任意のコードを実行されるおそれがある、かなり危ないものです。
使っているレンタルサーバー(XREA)は翌日の0時台にサーバー側の更新を済ませてくれたのですが、自分のサイトの設定を見てみたら、PHPは7.3のまま。7.3系には今回の脆弱性の正式な修正版が出ていません。さらにWordPressは5.2.21、テーマもプラグインも何年も放置……という状態でした。せっかくなので、一気に最新まで上げることにしました。
作業前と作業後
- PHP:7.3 → 8.3
- WordPress:5.2.21 → 7.1.3
- プラグイン・テーマ:すべて最新版に。使っていないものは削除
- SSL:wwwありだけ → wwwあり・なしの両方を常時SSL化
つまずき1:いきなりPHP 8.3にしたら表示されなくなった
最初、XREAのコントロールパネルでPHPをphp83に切り替えただけで、サイトに繋がらなくなりました。WordPress 5.2のような古いバージョンは、PHP 8系に対応していません。
一方で、最新のWordPress 7.1.3はPHP 7.4以上が必要なので、PHP 7.3のままでは本体を更新できません。結局、次の順番で段階的に上げるのが正解でした。
- バックアップを取る
- PHP 7.3のまま、プラグインを更新
- PHPを7.4に上げる
- WordPress本体を7.1.3に更新
- テーマ・プラグインを更新
- PHPを8.3に上げる
PHP 7.4も今回の脆弱性の正式な修正版がない古いバージョンなので、7.4の状態はあくまで途中経過として、同じ日のうちに8.3まで上げきりました。
つまずき2:プラグインの更新が cURL error 60 で失敗する
PHP 7.3のままプラグインを更新しようとしたら、全部「ダウンロードに失敗しました。」になりました。
cURL error 60: SSL certificate problem: unable to get local issuer certificate
WordPressは自分専用のルート証明書の一覧(wp-includes/certificates/ca-bundle.crt)を持っていて、5.2に入っているものは古すぎて、今のwordpress.orgの証明書を検証できなくなっていたのが原因でした。最新版のWordPressのzipから ca-bundle.crt だけを取り出して差し替えたら、更新できるようになりました。
つまずき3:PHP 8.3にしたら「重大なエラー」
本体とプラグインを最新にしてから、改めてPHPを8.3にしたところ、今度は「このWebサイトに重大なエラーが発生しました。」の画面に。wp-config.php でデバッグログを有効にして、原因を調べました。
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
wp-content/debug.log に出ていたのは、このエラーです。
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function WP_Widget::__construct(), 0 passed ... and at least 2 expected
スタックトレースをたどると、カテゴリーの並び替えに使っていたプラグイン「My Category Order」が原因でした。このプラグインのウィジェットは、クラス名と同じ名前のメソッドをコンストラクタとして使う、PHP 4時代の書き方をしています。PHP 8.0からはこの書き方がコンストラクタとして扱われなくなり、ただのメソッドになりました。その結果、親クラス WP_Widget の「引数2つ必須」のコンストラクタが引数なしで呼ばれて落ちていた、というわけです。C#だとクラス名と同じ名前のメソッドがコンストラクタなので、ちょっと意外な落とし穴でした。
長年更新されていないプラグインだったので、削除しました。調べ終わったら WP_DEBUG は false に戻して、debug.log も削除しておきます。
自作テーマの修正
このサイトは2012年に作った自作テーマで動いているので、テーマ側も今の環境に合わせて直しました。主な修正はこちらです。
register_sidebar()にidを指定(以前自動で割り当てられていたsidebar-1/sidebar-2を指定して、ウィジェットの設定を引き継ぎ)- Googleのサーバーから読み込んでいた jQuery 1.8.3 をやめて、WordPress同梱の jQuery・jQuery UI を使うように
- テンプレートやCSSに直書きしていた
http://のURLを、https や相対パスに - 宣言せずに使っていた
$postなど、PHP 8で警告になる書き方を修正 - 中身がほぼ空だった固定ページ用テンプレート(
page.php)を作り直し - サービスが終了している旧Googleアナリティクス(ga.js)と、IE8以前向けのスクリプトを削除
ついでに見た目も少し今風にしました。トップページの記事一覧を、Masonryの石垣のようなレイアウトから、CSS Gridできっちり行と列がそろうカード表示に変更。下までスクロールすると次のページを自動で読み込む無限スクロールにして、アイキャッチがない記事は本文の最初の画像をサムネイルに使うようにしています。
不要なプラグインとテーマの整理
停止中のプラグインや使っていないテーマも、ファイルがサーバーに残っている限り、脆弱性があれば狙われる可能性があります。なので、停止ではなく削除しました。古い試験版のまま残っていた Gutenberg プラグイン(ブロックエディタは今はWordPress本体に入っています)も削除。テーマは自作テーマと、予備として標準テーマの Twenty Twenty-Five だけを残しました。
ついでに常時SSL化
これまで https が使えたのは www.nyaou.com だけで、www なしの nyaou.com は http のままでした。XREAには「Main」に設定しているサイトには無料SSLを設定できない、という仕様があり、ここで少しハマりました。
- Main のドメインを、XREAのデフォルトドメインに変更
- 「サイト設定の新規作成」で nyaou.com を作り直し、同期設定を「する」(同期元は /public_html)、SSLを「無料SSL」に
- WordPressの「設定」→「一般」で、WordPressアドレスとサイトアドレスを https:// に変更
.htaccessの先頭に、http や www なしのアクセスを https://www.nyaou.com/ に転送する設定を追加- 記事の中に残っていた
http://の画像URLをhttps://に置き換え
.htaccess に追加したのはこれです。WordPressが書き換える # BEGIN WordPress 〜 # END WordPress の外側(ファイルの一番上)に置くのがポイントです。
# BEGIN https www redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^nyaou\.com$ [NC]
RewriteRule ^(.*)$ https://www.nyaou.com/$1 [R=301,L]
</IfModule>
# END https www redirect
記事の中に埋め込んでいた昔のAmazonアソシエイトの計測用画像も、サービスが終わっていて http のままだったので、この機会に取り除きました。
残っていること
WordPressのサイトヘルスで「古いデータベースサーバー」と出ています。XREAでは全サーバーのMariaDBを10.6系から11.4系へ順次更新中で、このサイトのサーバーはまだ順番待ちです。こちらはサーバー側の作業を待つだけなので、作業日が決まったらDBのバックアップを取っておこうと思います。
まとめ
何年も放置していた分、PHPとWordPressのバージョン差が大きく、思った以上に手順を踏む必要がありました。やってみて感じたポイントは、この3つです。
- WordPress本体を先に、PHPは後。新しいWordPressが要求する最低のPHPバージョンと、古いWordPressが動く最高のPHPバージョンの両方を確認して、段階的に上げる
- 困ったら debug.log。「重大なエラー」の画面だけでは何も分からないけど、ログを見れば原因のプラグインと、ファイル・行番号まで分かる
- 使っていないプラグイン・テーマは、停止ではなく削除
次回の更新は何年後かな~。