
PHP2Shell 対策と PHP バージョン:何を更新し、更新できないときはどうするか
フルスタック開発者
10月21日、PHP プロジェクトは二つの重大な脆弱性、CVE-2026-109618 と CVE-2026-109619 の修正版を公開しました。この二つは今、PHP2Shell と呼ばれています。どちらもログインなしで Web サーバー上のコードを実行でき、攻撃は修正版の公開より前に始まっていました。
修正はもうあります。ただし、サーバーを守るのはインストールされてからです。
php.net にリリースが出てから、そのリリースが自社のサーバーで動くまでには、時間差があります。この記事はその時間差についての話です。PHP2Shell は今すぐ対応が必要な問題ですが、同じ手順はどの PHP サイトにも、毎年当てはまります。
PHP のバージョンを確認する方法
この先の判断はすべてバージョン番号で決まります。最初にそこを確認してください。
- 自社で管理しているサーバー。 コマンドラインで
php -vを実行し、Web サーバー側が報告するバージョンも確認します(この二つが違うことがあります)。phpinfo()のページで確認できますが、読み終えたらすぐに削除してください。 - レンタルサーバー(共用ホスティング)。 管理画面の PHP 設定や PHP バージョンのメニューを開きます。一つの契約の中でもサイトごとにバージョンが違うことがあるので、全サイトを確認してください。
- WordPress。 管理画面の「ツール」から「サイトヘルス」を開き、「情報」タブの「サーバー」を見ます。サーバーにログインしなくても PHP のバージョンが表示されます。
- サーバーの外から、ブラウザで。 サーバーによっては、レスポンスヘッダーの
X-Powered-Byに PHP のバージョンが出ていて、ブラウザの開発者ツールの「ネットワーク」タブで見られます。このヘッダーを出さない設定のサーバーも多いので、表示がないことからは何も分かりません。 - Web 管理画面を持つ機器。 メーカーのセキュリティ情報で PHP2Shell を検索してください。影響がある場合、修正は php.net ではなく、メーカーのファームウェア更新として届きます。
8.2・8.3・8.4・8.5 を使っている場合
8.2.35、8.3.36、8.4.27、8.5.12 のいずれかに更新してください。二つの脆弱性を両方修正したリリースです。Linux ディストリビューションやホスティングの管理パネルのパッケージは、修正を取り込んでもバージョン番号が変わらないことがあるので、ベンダーのセキュリティ情報で CVE-2026-109618 と CVE-2026-109619 への対応も確認してください。php.net は Web リクエストを処理するすべての PHP が影響を受けるとし、PHP-FPM、mod_php を使う Apache、php-cgi、FrankenPHP、LiteSpeed を挙げ、認証なしのリクエストでもアプリケーションのコードが動く前に攻撃を起こせる mod_php の危険度が最も高いとしています。
更新したら、PHP のワーカー(リクエストを処理する PHP のプロセス)をすべて再起動します。FrankenPHP や LiteSpeed を使っている場合は、そのプロセスも再起動します。すでに動いている PHP-FPM や Apache のワーカーは古いコードをメモリに持ったままなので、新しいパッケージが入っていても、古い PHP でリクエストを処理し続けることがあります。再起動のあとは、コマンドラインだけでなく Web 側からもバージョンをもう一度確認してください。
更新後も、php.ini か PHP-FPM のプール設定で session.upload_progress.enabled=0 にし、ワーカーをすべて再起動して、次の PHP リリースまでそのままにしてください。10月のリリースで修正されていない CVE-2026-115560 も、この設定で防げます。この脆弱性は php.net が別の項目で説明していて、アプリケーションが session_start() の前に ini_set() で session.serialize_handler を php に切り替える場合だけ問題になります。この設定は ini_set() や .user.ini では不十分です。
8.2 を使っている場合は、もう一つ日付を覚えておいてください。8.2 のセキュリティサポートは2026年12月31日で終わります。その後に PHP2Shell のような脆弱性が見つかっても、8.2 向けのリリースは出ません。
7.4・8.0・8.1 を使っている場合(パッチとバックポート)
ここがいちばん難しいケースです。
PHP プロジェクトは、これらのブランチ向けのリリースをもう出していません。PHP2Shell については、セキュリティチームが 7.4・8.0・8.1 向けの最小限のソースバックポートを公開しました。ただしこれは PHP を自分でビルドする人向けのコード変更で、インストールすればよいパッケージではありません。
選べる道は三つです。
- ベンダーに確認する。 Linux ディストリビューション、ホスティングの管理パネル、長期サポートのベンダーの中には、独自にバックポートした修正を出しているところがあります。php.net も 8.1 以前の利用者にはそちらを案内しています。ベンダーのパッケージは古いバージョン番号のままで修正を含んでいることがあるので、自社の PHP ビルドが CVE-2026-109618 と CVE-2026-109619 に対して修正済みかどうかを、ホスティング会社やベンダーに直接確認し、回答を文書で残してください。
- バックポートからビルドする。 すでに PHP を自分でビルドしているなら、セキュリティチームのバックポートを使えばバージョンを変えずに修正を当てられます。その代わり、そのブランチの今後の修正もすべて自分で抱えることになります。
- サポート中のブランチに移行する。 アプリケーションを 8.4 か 8.5 に移します。本格的な開発作業が必要ですが、次の脆弱性で同じことをくり返さずに済む唯一の道です。
作業の大半はアプリケーションのコード側にあります。7.4 向けに書かれたコードは 8.x でそのまま動かないことが多く、PHP 8.0 で削除された関数があり、多くの警告がエラーに変わり、サイトが使っているライブラリ自体の更新が先に必要になることもあります。
バックポートで 7.4 の PHP2Shell は直せます。7.4 から抜け出せるのは、移行だけです。
だからこそ移行の計画は今すぐ始め、その間はサーバー側で守りを固めてください。
更新できるまでの PHP2Shell 緩和策
php.net は、部分的な対策でインストールが安全になることはないとはっきり書いています。そのうえで、更新が終わるまでの間に特定の攻撃経路を狭める手順を挙げています。
- セッションのアップロード進捗を無効にする。
php.iniか PHP-FPM のプール設定でsession.upload_progress.enabled=0にし、ワーカーをすべて再起動します。php.net によればこの設定はini_set()や.user.iniでは不十分で、確認済みのセッション経路は防ぐがほかの変種は防がず、同じ設定で、php.net が別の項目で説明している CVE-2026-115560 も防げます。この脆弱性は、10月のリリースではまだ修正されていません。 - PHP のメモリ制限を外す。 アプリケーションが上書きできないよう、PHP-FPM のプールか Apache の設定で
php_admin_valueを使ってmemory_limit=-1にし、プール、ディレクトリ、アプリケーションのどの設定も有限の上限を戻していないか確認します(php.net はこれを CVE-2026-109618 の対策の最初に挙げ、元になるメモリ確保の失敗はそれでも脆弱な処理に届くことがあると警告しています)。上限をなくすと、1つの暴走したリクエストがホストのメモリをすべて使えるので、後述のコンテナや cgroup の上限と組み合わせてください。 - リクエストサイズを制限する。 アップロードのないサイトなら
post_max_sizeを8M、あるなら32Mにし、upload_max_filesizeはそれより小さくします。これで CVE-2026-109618 への経路の一つが狭まります。 RLIMIT_ASとRLIMIT_DATAは使わない。 php.net は、この2つの上限が同じメモリ確保の失敗を引き起こすことがあると警告しています。代わりにコンテナや cgroup の上限を使い、できれば問題のあるワーカーだけを停止する設定にします。- PHP 8.5 では、致命的エラーのバックトレースを無効にする。
fatal_error_backtraces=0にし、ワーカーをすべて再起動します。php.net によれば、これで防げるのは確認済みの致命的エラーのバックトレース経由の経路だけです。 - WAF(Web アプリケーションファイアウォール)を前段に置く。 Cloudflare は PHP2Shell 向けのファイアウォールルールを公開しているので、自社のプロバイダーにも同様のルールがあるか確認してください。ルールで時間は稼げますが、更新が必要なことは変わりません。
各手順の条件を含む全リストは、php.net のセキュリティアドバイザリにあります。
すでに侵入されていないか確かめる
PHP2Shell は修正版の公開より前から狙われていました。Amazon の脅威インテリジェンスチームは、リリースの4日前の10月17日に攻撃の試みを記録し、侵害は公表より前に起きている可能性があると述べています(Amazon Security Blog)。更新が済んだら、誰かがすでに入り込んでいないか確認してください。
- アップロード先の新しい PHP ファイル。 画像だけが入っているはずのアップロードフォルダで10月17日以降に更新された
.phpファイルを探し、キャッシュや一時ファイルのフォルダは、アプリケーション自身が作るファイルと突き合わせます。Web シェルは更新日時を偽装できるので、何も見つからなくても安全の証明にはなりません。 - スケジュールタスクとアカウント。 cron の設定と管理者ユーザーに、チームの誰も追加した覚えのないものがないか確認します。元の穴をふさいだあとに戻ってくるための入口として、よく使われる手口です。
- 外向きの通信。 ファイアウォールやサーバーのログで、Web サーバーから見覚えのない宛先への通信を探します。Web サーバーが自分から接続を始める必要は、ほとんどありません。
何か見つかったら、そのファイルを消すだけで終わらせないでください。既知の正常な状態からサーバーを作り直し、そのサーバーが持っていたパスワードと鍵をすべて変更します。
毎年くり返す、同じ問い
PHP はおおむね年に一度、年末ごろに新しいブランチを出します。各ブランチには2年間のアクティブサポートと、さらに2年間のセキュリティ修正があります。PHP のバージョンを一度も変えないサイトは、自社のコードがどうであれ、そのバージョンの公開から4年でサポートが切れます。

セキュリティリリースの適用は、名前のある担当者と、カレンダーの日付がそろってはじめて進む作業です。写真: Derrick Coetzee(NERSC)、CC0、Wikimedia Commons より。
その日付より前に、答えておきたい問いが三つあります。
- このサーバーの PHP を更新するのは誰か。 特定の担当者の名前が出てくるべきです。「ベンダー」や「情シス」という答えで、最後にいつ更新したか誰も知らないなら、実際には誰も更新していません。
- 今のバージョンのセキュリティサポートはいつ終わるか。 日付は php.net のサポート対象バージョンのページに載っています。本番公開の日に、カレンダーへ入れておいてください。
- 次のバージョンに上げると何が壊れるか。 数か月前に、テスト環境で次のバージョンを試してください。緊急時に知るより、ずっと安く済みます。
マレーシアやシンガポールで PHP サーバーの保守を任せられる相手を探している場合は、お手伝いできるかもしれません。私たちの進め方はこちらです。
お問い合わせ:[email protected]
ヘッダー写真: Victor Grigas, CC BY-SA 3.0, cropped, via Wikimedia Commons (https://commons.wikimedia.org/wiki/File:Wikimedia_Foundation_Servers-8055_22.jpg)
