2026.09.23 泊まれる場所4,223 立ち寄りスポット59,693 営業中を確認したキャンプ場1,005 note を読む

PHPの緊急脆弱性CVE-2026-109618の修正版が出た|確かめるのはphp -vではなく、Webで動いている方の版

PHPの緊急脆弱性2件の修正版(8.5.12・8.4.27・8.3.36・8.2.35)が出た。
ファイル添付のフォームが無いサイトも対象。
Webで動いている版の確かめ方、更新の順番、公式の暫定策を設定名つきでまとめた。

PHPの緊急脆弱性2件(CVE-2026-109618・CVE-2026-109619)の修正版が、日本時間の10月21日23時に出ました。
番号は 8.5.12・8.4.27・8.3.36・8.2.35 で、これより前の版は全て影響を受けます。
ファイル添付のフォームが無いサイトも対象なので、PHPのサーバーを触れる人は更新の段取りを始めてください。

この記事は、サーバーを自分で触る人向けに、手を動かす順番で書きます。
Webで動いている版の確かめ方、更新の順番、公式の暫定策の設定名、multipart を使わないURLの止め方です。
一般向けにまとめた版は note に書きました(末尾にリンクがあります)。

※ 2026年10月21日夜(日本時間)時点の、PHP公式の告知と GitHub の脆弱性情報2件をもとに書いています。

2件の脆弱性の中身

深刻度はどちらも CVSS v4.0 で 9.2(Critical)です。
認証なしで、外からサーバー上の任意のコードを実行される恐れがあります。

  • CVE-2026-109618:メモリ不足(OOM)で処理を打ち切る時に、作りかけの内部データが残ります。後片付け(shutdown)の処理が、それを正しいデータとして扱ってしまう不具合です。multipart の解析を細工して、わざとメモリ不足を起こさせるのが入口です。
  • CVE-2026-109619:リクエスト専用の内部状態が、解放された後もワーカーに残ります。同じワーカーが次のリクエストを処理する時に、初期化の前にそれを参照してしまう use-after-free です。入口は session.upload_progress(初期設定で有効・session_start() 不要)、mod_php の .htaccess の php_value などが出す早い段階の設定警告、PHP 8.5 の fatal_error_backtraces です。

公式の告知で最も危険とされているのは、Apache の mod_php です。
認証なしのリクエストで、アプリのコードが動く前に攻撃が成立することが実証されています。
PHP-FPM でも、109619 の upload progress の経路で任意コード実行が確かめられています(アプリ側の条件つき)。

実際に悪用されたかどうかは、公式の情報には書かれていません。
ただ、研究者の検証は済んでいて、技術的な中身も公開されています。
僕は「まだ攻撃されていない」を、更新を待つ理由にはしないつもりです。

対象は、Webのリクエストを処理している全てのPHP

公式が挙げているのは PHP-FPM・Apache mod_php・php-cgi・FrankenPHP・LiteSpeed です。
動かし方を問わず、Webから届くリクエストを PHP が処理していれば対象です。

見落としやすいのが、アップロード機能の有無です。
multipart のリクエストは、受け取る側にフォームがあるかどうかに関係なく、PHPで動くどのURLにも送れます。
109618 の advisory も、multipart を使わないアプリはフロント(Webサーバーやプロキシ)で止めるよう書いています。

Webで動いている版の確かめ方

最初の落とし穴は php -v です。
これはコマンドライン用(CLI)のPHPの版で、Webのリクエストを処理しているPHPとは別のことがあります。
CLIだけ新しくて、Webの方は古いまま、ということは普通に起きます。

  • PHP-FPM:FPM 自体の版を見ます(php-fpm -v。配布元によって php-fpm8.3 -v や /usr/sbin/php-fpm -v のように名前が違います)。複数の版の FPM が同居しているサーバーでは、Webサーバーの設定がどのソケットに渡しているかまで確かめます。
  • mod_php:Apache に読み込まれているモジュールの版です。apachectl -M で PHP のモジュールが載っているかを見て、そのモジュールのパッケージの版を確かめます。
  • レンタルサーバー:管理画面のPHPの版の設定と、サーバー会社のお知らせを見ます。

配布元のパッケージは、版の番号を上げずに修正だけを取り込む(バックポートする)ことがあります。
その場合は番号だけでは判断できないので、パッケージの変更履歴に CVE 番号が載っているかで確かめます(RHEL 系なら rpm -q --changelog、Debian 系なら apt changelog など)。

確認のために phpinfo() のファイルを公開領域に置くのは避けたいところです。
消し忘れると、それ自体が攻撃する側の下調べに使われます。

更新の順番

  1. 本番のバックアップを取る(ファイルとDB)。
  2. 検証用の環境で先に上げて、画面・フォーム・管理画面・定期実行が動くかを見る。
  3. 本番を上げる。
  4. PHP-FPM か Apache を再起動して、全ワーカーを入れ替える。パッケージを入れ替えただけでは、動いているワーカーが古いまま残ることがあります。
  5. Webで動いている版(または変更履歴の CVE 番号)を、もう一度確かめる。

Linux の配布元と LTS のベンダーには、修正が事前に渡されています。
公式も、配布元の更新パッケージを確認するよう案内しています。

remi から入れている場合と、8.1 以前の場合

有志が運営している remi リポジトリ(rpms.remirepo.net)は、公式の告知に「当日は更新なし」と書かれていました。
配布元のパッケージへ切り替えるか、ソースからビルドするよう勧められています。

8.1 以前には、公式の更新は出ません。
7.4・8.0・8.1 向けには、最小限のソースパッチが GitHub のブランチで提供されています。
自分でビルドして当てられる人向けなので、多くの場合は 8.2 以降への移行が本命になると思います。

移行先を選ぶ時に気をつけたいのが、8.2 のサポートが 2026年12月31日で終わることです。
今 8.2 へ上げると、2か月ほどでもう一度上げることになります。
アプリが動くなら、僕は 8.3 以降を選びます。

更新までの暫定策(設定名つき)

公式は「完全な回避策は無い。更新だけが安全」と書いています。
暫定策は、確かめられた攻撃の道筋を減らすだけです。
更新の日までのつなぎとして使います。

  • session.upload_progress.enabled=0:php.ini、FPM のプール設定、Webサーバーの設定のどれかに書き、全ワーカーを再起動します。ini_set() と .user.ini では効きません。ini_set() はスクリプトが動き始めてからの設定なので、リクエストの本文を読む段階には間に合いません。.user.ini も公式が効かないと明記しているので、ワーカーが起動する時に読む設定で切る、と覚えておくのが安全だと思います。
  • post_max_size:アップロードが不要なら 8M、必要なら 32M。upload_max_filesize は post_max_size より小さくします。
  • memory_limit=-1:php_admin_value(FPM のプール設定や Apache の設定)で固定し、下位の設定で戻されないかを確かめます。上限が無くなるぶん、cgroup などワーカー単位のメモリ制限と組み合わせます。PHP 自身がメモリ不足で処理を打ち切る経路(109618)を通らせないための設定だと、僕は読んでいます。
  • fatal_error_backtraces=0(PHP 8.5 のみ):入れたら全ワーカーを再起動します。
  • リクエストのたびに警告が出る設定を消す:不正な値や非推奨の設定は、初期化の前に警告を出し、109619 の入口になります。error_reporting・display_errors・@ では防げません。mod_php なら .htaccess の php_value も見直します。

multipart を使わないURLは、Webサーバーで止める

アップロードを受け付けるURLは、サイトの中でも限られています。
それ以外のURLに届く multipart の POST は、PHP に渡す前に Web サーバーで断ってしまう、というのが考え方です。

  1. アップロードを受け付けるURL(管理画面のメディア登録、添付つきの問い合わせなど)を洗い出す。
  2. それ以外のパスで、Content-Type が multipart/form-data のリクエストを 403 などで返す。
  3. 残したアップロードの入口が、ログイン必須になっているかを確かめる。

書き方の一例です。
アップロードを受け付けるパスには当てないよう、環境に合わせて範囲を絞ってください。

# nginx(アップロードを受け付けない location の中)
if ($http_content_type ~* "^multipart/form-data") { return 403; }

# Apache(mod_rewrite。/upload/ はアップロードを受け付けるパスの例)
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/upload/
RewriteCond %{HTTP:Content-Type} ^multipart/form-data [NC]
RewriteRule ^ - [F]

入れたら、アップロードのあるページで実際にファイルが送れることを確かめます。
止めすぎて管理画面の画像登録が動かなくなるのが、いちばんありそうな失敗です。

公式は、リクエストの大きさ・入力項目の数・multipart の part の数・ヘッダーの数・入れ子の深さを、Webサーバーやプロキシで制限することも勧めています。
Content-Length の無いリクエストにも効くようにする、という注記つきです。
nginx なら client_max_body_size、Apache なら LimitRequestBody・LimitRequestFields あたりが入口になります。

僕が今夜やったこと

修正版の番号が出てから、僕が管理しているサーバーで次のことをしました。

  • PHPの版の一覧を作り直し、どのサーバーをどこまで上げるかを1行ずつ書き足した。
  • ファイルを受け取る機能が無いURLへの multipart の POST を、Webサーバーで PHP に渡る前に止めた。
  • 管理用 API のファイル受け取り口を認証必須にした。アップロード先では、スクリプトを実行させない設定にした。
  • 公開フォルダに残っていた PHP の控えファイルを外し、控えファイルの配信を拒否する設定を入れた。

控えのファイルは、今回の脆弱性とは別の話です。
こういう点検の時に、別の穴が見つかるのはよくあることだと思います。
公開領域に置いてはいけないものを毎週確かめている話は、露出チェックを流した回に書きました。

あとは、配布元の修正パッケージを待って更新します。
サポートが終わったOSで動いていて、通常の更新では修正版が入らないサーバーもあります。
そこは移行を前倒しにします。

やることの順番

  1. Webで動いているPHPの版を確かめる(php -v だけで済ませない)。
  2. 8.5.12・8.4.27・8.3.36・8.2.35 より前なら、バックアップ→検証環境→本番の順で更新し、ワーカーを再起動する。
  3. すぐ更新できないサーバーは、暫定策を入れて全ワーカーを再起動する。
  4. multipart を使わないURLは、Webサーバーで止める。
  5. 8.1 以前は 8.2 以降(できれば 8.3 以降)への移行を決める。remi から入れている場合は、入れ方を切り替える。

一般向けに「何が起きたか・何をすればよいか」をまとめた版は、note に書きました。
PHPの緊急脆弱性の修正版が出た。ファイル添付のフォームが無いサイトも対象だった(note)

※ 調査と下書きは、AI(Claude)と一緒に行いました。一次情報の確認、内容の判断、サーバーでの作業と公開は僕が行っています。

出典

まる子パパ

まる子パパ

会社員。受託開発のエンジニアを15年以上続けていて、その前は寿司職人・長距離運転手・農業。 技術ブログは、キャンプの合間に踏んだバグと、AI・Web開発の運用の失敗を書いています。 このサイト自体が、開発に携わっているCMS「コンテナ」の稼働中の実例です。 このサイトについて / 小さな自動化の相談

—

ほかにも書いています

受託・note・スタンプ

※受託の相談とnoteは、運営者が個人で受けている・書いているものです。

技術ブログ一覧へ戻る