CVE-2026-109618
アップロード進捗のアンシリアライザにおける use-after-free
セッションモジュールは、リクエストの初期化が終わる前にアップロード進捗の追跡用データをデコードし、BG(unserialize) に管理情報を保持します。メモリ確保に失敗するとリクエストのヒープは破棄されますが、このグローバル変数は残ります。同じワーカーの次のリクエストは、攻撃者が再利用したメモリを有効なアンシリアライザの状態として扱います。
技術解説
原因は 1 つ、CVE は 2 つ、バグは 4 つ:PHP は、リクエスト処理の途中で致命的エラー——特にメモリ枯渇——が起きたとき、確実に後片付けができません。
最終確認 2026-10-22
PHP は memory_limit に達すると致命的エラーを発生させ、longjmp() で巻き戻ります。このとき、状態の初期化やリセットを完了させるはずのコードが飛ばされます。その結果、2 つの問題が起きます:
攻撃者は細工した multipart リクエストでこれらの経路に到達し、入力の解析中に PHP を OOM に追い込みます——ルーター、フレームワーク、認証が動く前の段階です。だからこそ「Hello World」スクリプトも WordPress と同じように危険にさらされます。
ステップ 1
漏えい
メモリ漏えいを使ってワーカーの実行中のメモリを読み、ASLR を無効化する。
ステップ 2
破壊
use-after-free(アンシリアライザまたはバックトレース)を使って、制御したデータを書き込む。
ステップ 3
実行
メモリ破壊をワーカーユーザーとしてのコード実行に変える——ログイン前に。
悪用は一発では成功しません。攻撃者は標的ごとのメモリ配置に合わせるため、何度も探りを入れます。研究者はこのチェーンを php2shell というスクリプト(非公開)にまとめ、当時最新の wordpress、drupal、joomla のコンテナイメージで実証しました。
CVE-2026-109618
アップロード進捗のアンシリアライザにおける use-after-free
セッションモジュールは、リクエストの初期化が終わる前にアップロード進捗の追跡用データをデコードし、BG(unserialize) に管理情報を保持します。メモリ確保に失敗するとリクエストのヒープは破棄されますが、このグローバル変数は残ります。同じワーカーの次のリクエストは、攻撃者が再利用したメモリを有効なアンシリアライザの状態として扱います。
CVE-2026-109618
プロセスメモリのリモート漏えい
RFC 1867 の multipart 解析の初期段階で、アップロード進捗のコードがセッション ID を PS(id) に公開することがあります。OOM による中断の後、このポインタは宙に浮いた状態になります。その後の multipart リクエストがポインタと長さを信用し、そこに今ある内容を URL エンコードして PHPSESSID Cookie に書き込みます——アプリが session_start() を呼ばなくても起こります。
CVE-2026-109619
致命的エラーのバックトレースにおける use-after-free
EG(last_fatal_error_backtrace) は、リクエストのヒープを破棄する OOM の後も残ります。次のリクエストの初期段階の診断処理が、この宙に浮いたポインタをたどります。fatal_error_backtraces を有効にした PHP 8.5 で最も直接的です。
CVE-2026-109619
OPcache 共有メモリにおける型の取り違え
zend_accel_script_persist() では、共有領域の境界が公開される前に CG(map_ptr_last) が進みます。その間でメモリ確保に失敗すると、ワーカー間で認識が食い違う map-pointer のスロットが残り、あるワーカーがそのスロットを別の型のオブジェクトに再利用できてしまいます。
バグと CVE の対応は Wiz Research の記事に基づいています。PHP のアドバイザリはクラスをより広く記述し、さらなる亜種にも言及しています。
PHP のアドバイザリに基づきます。「影響あり」は、ソース解析で脆弱と判断されたものの、その SAPI 向けの汎用エクスプロイトは公開されていないことを意味します。
| 構成 | …109618 | …109619 | 補足 |
|---|---|---|---|
| Apache + mod_php | RCE 確認済み | RCE 確認済み | 両 CVE ともデフォルト制限で RCE まで確認済み。最もリスクの高い構成です。 |
| PHP-FPM(nginx、Apache、Caddy など) | 影響あり | RCE 確認済み | セッションのライフサイクル経由の RCE が FPM で確認済み。OOM 経路はアプリケーション層のコードパス経由で確認されていますが、汎用的な FPM 向けエクスプロイトは公開されていません。 |
| FrankenPHP / LiteSpeed LSAPI | 影響の可能性大 | 影響の可能性大 | アドバイザリでは影響の可能性が高いとされています。常駐ワーカーでは、リクエストをまたいだ残留状態の問題がむしろ大きくなります。 |
| CLI(cron、キューワーカー、artisan) | 対象外 | 対象外 | アドバイザリでは扱われておらず、通常の使い方では HTTP リクエストから到達できません。ただし同じパッケージなので、いずれにせよ更新してください。 |
メモリ枯渇(OOM)時の破損による RCE
PHP はメモリが枯渇すると longjmp() で現在のコンテキストを中断します。それがリクエスト用メモリの初期化途中に起きると、後のリクエスト終了処理で無効なデータを読んだり、それに基づいて分岐したりします。複数の multipart 解析経路で、通常の制限内でも PHP を OOM に追い込めます。しかもアプリケーションコードが動く前の段階です。
リクエストをまたいで残るグローバル状態による RCE
致命的エラー(OOM を含む)によってリクエストごとのリセットが飛ばされ、エラー・セッション・オブジェクト・拡張機能のグローバル状態が、リクエスト終了時に解放されたメモリを指したままになることがあります。同じワーカーの次のリクエストが、通常の初期化より前にその解放済みメモリを使ってしまいます。
ベクトル(両方とも):CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N。ネットワーク経由で到達可能、権限もユーザー操作も不要。「AC:H / AT:P」は、エクスプロイトを標的に合わせて調整する必要があることを示しています。漏えい直後の報道にあった CVSS 10.0 は誤りです。
パッチでは、メモリ枯渇時に longjmp() を使わなくなりました。代わりに、memory_limit に達するとソフト OOM が設定され、状態が整合している VM の次の安全なポイントで発生します。さらに高い 2 つ目のしきい値に達するとハード OOM が発生し、_exit() でプロセスを終了します——シャットダウンハンドラは動かず、中途半端に片付いた状態も残りません。
個々の入口ではなく不具合のパターンそのものを修正しているため、既知の亜種もカバーしていると PHP チームは述べています。
副作用:OOM の後もシャットダウン関数が動くことを前提にしていたコードは、ハードリミットに達した時点で挙動が変わります。