2026 年 10 月 22 日時点でソースを確認。 対象者: PHP アプリケーション オペレーター、セキュリティ レスポンダー、およびカスタム PHP ビルドを維持するエンジニア。
この記事では、PHP2Shell 脆弱性の原因、影響範囲、正式な修復プロセス、一時的な緩和策、公式パッチの実装についてまとめています。本文は S1 などの番号を使用して引用されます。すべてのソースリンクは本文の最後にある付録にリストされています。構成フラグメントは展開テンプレートであり、実際のバージョン、ビジネス容量、構成の継承関係に基づいて調整する必要があります。
TL;DR: 修復手順と提案
- アップグレードする PHP ランタイム : 関連するブランチを少なくとも次のレベルにアップグレードします。 8.2.35 , 8.3.36 , 8.4.27 または 8.5.12 。配布パッケージの場合は、ベンダーが両方の CVE を修正することを確認した完全なパッケージ バージョンを使用してください。 S1 S10
- すべての古いプロセスを置き換えます: アップグレード後にすべての PHP worker、ホスティング サービス、コンテナーを再起動またはロールオーバーし、古いインスタンスが終了していることを確認します。
- 実際の Web リクエスト パスを通じて検証します: Web SAPI、完全なパッケージ バージョン、および実行中のインスタンスを確認します。
php -vだけをチェックしても、ライブ サービスが修正されていることは確認できません。 - Rビジネス回帰チェックを実行し、通常のリソース予算を復元します: ログイン、セッション処理、アップロード、インポート、およびエラー処理をテストします。 PHP メモリ制限が一時的に削除された場合は、パッチ適用後に適切な有限バジェットを復元します。
- すぐにアップグレードできない場合 : 信頼できないトラフィックが到達する前に制限します。 PHP 。アップロードの進行状況の無効化を評価し、 PHP 8.5 セクション 5 で説明されている致命的なバックトレース。構成の軽減策と WAF このルールは適用範囲が限られており、アップグレードを置き換えることはできません。 S1 S2 S3
1. 脆弱性の概要とリスク判断
PHP2Shell この記事では 2 つのことを指します Critical によって公式に公開されたレベルの脆弱性 PHP どちらもメモリとリクエストのライフサイクル管理に関連しています。 PHP エンジンに影響を与え、認証されていないリモート コードが実行されるリスクがあります。 S1 S2 S3
| プロジェクト | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| 正式名称 | RCE via OOM corruption | RCE via stale global state |
| 核心的な問題 | メモリが不足すると異常ジャンプが発生し、初期化が完了していない状態になります。 | ワーカーに残っているグローバル状態は、解放されたリクエスト メモリを指します。 |
| 典型的な発生時間 | 現在のリクエストの初期化、実行、またはクリーンアップのプロセス | 前のリクエストはステータスを残し、後続のリクエストはステータスを事前に消費します。 |
| OOMは必須条件ですか? | 脆弱性の中核となるトリガーメカニズムに属します | いいえ。他の致命的なエラーや診断後のクリーンアップも関係する可能性があります |
| 根本的な修理の方向性 | 割り当ての失敗と終了要求を安全に処理する | 状態の所有権、クリーンアップのタイミング、早期の初期化を修正 |
| 廃棄要件 | 修理しなければならない | 同時に修理する必要があります |
根拠: 2 つの公式セキュリティ情報と修正プログラムの提出。 S2 S3 S4
1.1 影響を受ける展開の理解
PHP 正式に検討します 全て PHP デプロイメントの処理 Web リクエスト リスクにさらされているものを含む PHP-FPM , Apache mod_php , php-cgi , FrankenPHP 、 そして LiteSpeed 。実証された mod_php 攻撃はアプリケーション コードが実行される前に発生する可能性があるため、ログイン チェック、フレームワーク ミドルウェア、アプリケーションのアップロードの検証ではそのパスをカバーできません。 S1
「デプロイを修正する必要がある」と「特定の攻撃チェーンが完全に証明されている」を区別する必要があります。の発表 CVE-2026-109618 : FPM リクエストの起動が失敗した後、子プロセスを終了し、対応するクリーンアップ パスをブロックします。 mod_php 起動失敗後。ただし、 OOM 正常に起動した後のパスは依然として危険にさらされています。発表では、完全な FPM これを悪用する CVE まだ実証されていない。この制限を使用して次のことを推測することはできません。 FPM 特に安全です CVE-2026-109619 無視することはできません。 S2 S3
悪用が成功するための直接のアクセス許可の境界は、PHP をホストしているプロセスの ID と、そのプロセスがアクセスできるリソースによって異なります。一般に、Web サイトのコード、アップロード ディレクトリ、データベースの資格情報、サービス トークン、および内部ネットワーク アクセス機能に注意を払う必要があります。 「リモートコード実行」とは、自然に root 権限を取得することを意味するものではありません。ここでの結果の判断はプロセス権限モデルに基づいており、実際の影響は展開権限と組み合わせて評価する必要があります。
通常のワンタイム CLI スクリプトには、同じ HTTP エントリがありません。ただし、CLI または組み込みモードで外部タスクを長時間処理するプロセスは、引き続きランタイムおよびライフサイクル インベントリに含める必要があります。 CMS、フレームワークまたは Composer の依存関係のみが更新され、基礎となる PHP エンジンは自動的に置き換えられません。
2. 原因分析
2.1 まず 2 つのライフサイクルを理解する
PHP worker は、複数のリクエストを連続して処理することがよくあります。リクエスト中に割り当てられたメモリは、ワーカー自体とそのグローバル フィールドの一部が引き続き存在している間、リクエストの終了時に一律に解放できます。
したがって、エンジンは次の 2 つの制約を維持する必要があります。
- 初期化制約: 他のコードから見えるデータは、安全に読み取り、横断、破棄できる状態でなければなりません。
- ライフサイクル制約: リクエスト メモリが解放されると、有効期間の長いフィールドはそのメモリ内のアドレスを有効な状態として扱い続けてはなりません。
これら 2 つの制約は、2 つのグループの脆弱性の主な障害モードに対応しています。以下のプロセスは、アナウンスとパッチのコンパイルを組み合わせたメカニズムの説明です。すべてのデプロイメントにまったく同じ到達可能なパスがあるという意味ではありません。 S2 S3 S5
2.2 CVE-2026-109618: OOM は未完了のステータス更新を中断しました
古い実装では、longjmp() タイプの非ローカル ジャンプを使用して OOM を処理し、関連付けられたパスは zend_bailout() を介して現在の実行コンテキストを終了します。危険なのは、C コードの一部が新しいオブジェクト、配列、またはリクエスト ステータスを他のコードに公開している可能性がありますが、すべてのフィールドの初期化がまだ完了していないことです。このとき、該当する時点で割り当てに失敗すると、通常の終了ステップがスキップされる可能性があります。 S2
失敗のプロセスは 4 つのステップに分類できます。
- リクエストの内部構造を作成または更新し、アクセスできるようにします。
- 後続のメモリ割り当ては失敗し、OOM がトリガーされます。
- 実行フローは現在の関数からジャンプし、初期化を完了したり状態を復元したりするために元々使用されていたコードは実行されません。
- リクエストのクリーンアップはこれらの構造の処理を続行し、無効なコンテンツを有効なフィールドまたはアドレスとして扱います。
問題は、メモリ不足が常に RCE を引き起こすということではありません。むしろ、メモリが枯渇すると制御フローが変更され、有効な構造に関するエンジンの前提条件に違反します。失敗した割り当ては、最終的に誤って読み取られる構造に直接関係している必要はありません。 S2
小さいリクエストでもメモリ不足になる理由
リクエスト本文のバイト数と解析後のヒープ使用量は同じではありません。 A フィールドは、PHP 内の複数の文字列、配列要素、メタデータ オブジェクトに対応する場合があります。入力された構造の複雑さは、メモリの増幅の程度に影響します。
公式発表に記載されているマルチパートの問題には、利用可能な宣言長が欠落している場合の初期サイズ チェックのギャップ、単一パートのヘッダー数が十分に制限されていない、空のファイル コントロールが依然としてメタデータを生成し、ネストされた名前により配列のワークロードがさらに増加していることが含まれます。アプリケーション自身の入力の巻き戻し、デコード、または再割り当ても、OOM の原因となる可能性があります。 S2
これから 2 つの保護的な結論を導き出すことができます。
- リクエスト本文の制限は、PHP を入力する前にできる限り実装する必要があり、実際の読み取り長と構造の複雑さを考慮する必要があります。
- ファイル サイズやファイル数を個別に制限したり、アップロード ポータルを 1 つだけ閉じたりした場合、すべての OOM ソースをカバーすることはできません。
アプリケーションの認証が遅すぎる理由
で mod_php 、リクエストの本文はリクエストの初期化フェーズ中に自動的に解析される場合があります。起動に失敗した場合でも、関連するリクエストのクリーンアップは引き続き実行されます。したがって、確認された攻撃パスはアプリケーション コードの前に発生する可能性があります。この段階で露出を減らすには、リバース プロキシに制限を設ける必要があります。 Web サーバー、またはそれに先行する他の境界 PHP リクエスト処理。 S1 S2
2.3 CVE-2026-109619: リクエスト メモリは解放されました。グローバル参照はまだ生きています。
この問題には、エラー、セッション、オブジェクト、または拡張機能のステータスが関係しています。フィールドはワーカーの長期アクセス場所に保存されていますが、フィールドによって参照されるデータは単一のリクエストに属しています。リクエスト ヒープが解放される前に参照が適切にクリーンアップされない限り、後続のリクエストはダングリング状態に陥り、use-after-free が形成される可能性があります。 S3
公式分析では、悪用条件を「生産者」と「消費者」に分けています。
| 役割とか条件とか | 意味 | 保護への影響 |
|---|---|---|
| 州プロデューサー | このリクエストが所有する状態を、後でアクセスできる場所に配置します。 | 異常終了後に対応するクリーンアップが完了したかどうかを確認するには |
| ステータスはそのまま | クリアされなかったか、クリアされた後、後の操作で補充されました。 | シャットダウンの初期段階で一度クリアするだけでは不十分な場合があります |
| ワーカーの再利用 | 同じワーカーが後続のリクエストを処理し続けます | 複数のワーカーは単なるスケジュールの違いであり、メモリの安全性が保証されるものではありません |
| 先進的な消費者 | 対応する状態が正常に初期化される前に、残存値を読み取る、解放する、または決定します。 | 初期化前にINI、セッション、その他のパスを確認する必要があります |
これらの条件は組み合わせて満たす必要があります。エラー ログ自体は、脆弱性が悪用されたことを証明するものではありません。 S3
必要な前提条件として OOM は必要ありません
致命的なエラーにより、ペア状態の公開と復元が中断される可能性があります。コンパイルまたは解析の失敗、捕捉されなかったエラー、require の失敗、実行タイムアウトにより、特定の状態が残る可能性があります。クリーンアップの後半で致命的ではない診断を行うと、すでに消去されたエラー情報が再入力される場合もあります。 S3
したがって、memory_limit を無制限に変更しても、この一連の脆弱性はカバーされません。
「初期化前」は別個に扱う必要がある
2 種類の確認済みコンシューマのタイミングは異なります。
- E初期の INI 診断: リクエストに適用される一部の構成では、通常のエグゼキューターの初期化の前に警告、通知、または非推奨が発行され、診断処理で古いエラー状態にアクセスする場合があります。
- session アップロードの進行状況: セッションはリクエスト本文の解析プロセス中に事前に処理される可能性がありますが、通常のモジュール
RINITはまだ完了していません。アプリケーションが明示的にsession_start()を呼び出していないため、パスが存在しないと推論することはできません。 S3
すべての INI 構成のリスク タイミングが同じであるわけではありません。 FPM フロントエンドによって渡される mod_php および PHP_VALUE / PHP_ADMIN_VALUE のディレクトリ レベルの構成は、通常の php.ini、FPM pool スタートアップ構成、および FPM .user.ini と区別する必要があります。後者は構成タイミングが異なるため、まとめて同じ初期コンシューマと呼ぶことはできません。 S3
display_errors、log_errors をオフにする、error_reporting を減らす、または @ を使用することは、診断の可視性にのみ影響します。ログを出力するかどうかを決定する前に、関連する内部状態にアクセスされた可能性があります。 S3
3. 修復バージョンとパッチの選択
3.1 公式アップストリーム修正ベースライン
| 現在の PHP ブランチ | この公式修正が含まれる最初のバージョン | 提案 |
|---|---|---|
| 8.2 | 8.2.35 | このバージョン、または同じ修正を含む後続のバージョンにアップグレードします。 |
| 8.3 | 8.3.36 | 同上 |
| 8.4 | 8.4.27 | 同上 |
| 8.5 | 8.5.12 | 同上 |
| 8.1 以前のバージョン | アップストリームの一般サポートは終了しました | サポートされているブランチへの移行を優先します。短期チェックリリースまたはLTSメーカーバックポート |
バージョンや対応状況は公式発表に基づくものです。 PHP 、時間の基準は 2026 年 10 月 22 日です。 S1
これらは ブランチ固有の修正しきい値 です。これらを、8.5.12 以下のすべてのバージョンに脆弱性があるという言葉で置き換えることはできません。他のブランチの 8.2.35 や 8.4.27 などのバージョンには、すでに修正が含まれています。
3.2 完全な配布パッケージのバージョンを確認してください
ディストリビューションは、古いアップストリーム バージョンに基づいてセキュリティ修正を追加することがよくあります。同意するには、リリース バージョン、リポジトリ ソース、完全なパッケージ バージョン、およびセキュリティ情報も確認する必要があります。
たとえば、Ubuntu USN-8948-1 にリストされている Ubuntu 24.04 LTS 修正パッケージのバージョンは次のとおりです。
8.3.6-0ubuntu0.24.04.13
そのアップストリーム部分は依然として 8.3.6 ですが、そのディストリビューションの完全なパッケージ バージョンがこの修正の発表に含まれています。この結論は、対応するディストリビューションおよびパッケージ ソースにのみ適用され、8.3.6 も表示されるビルドに一般化することはできません。 S10
3.3 適切なパッチの選択
| シーン | 優先計画 | 受け入れのための重要なポイント |
|---|---|---|
| 配布 PHP パッケージの使用 | メーカーがリリースしたセキュリティアップデートをインストールする | この発表では、CVE の両方がカバーされています。完全なパッケージのバージョンは正しいです |
| 公式の PHP コンテナまたは自己構築イメージを使用してください | 基本ランタイムを更新し、再構築してデプロイする | 実行中のインスタンスは新しいイメージを使用します。古いコピーはすべて終了します |
| セルフコンパイルでサポートされるブランチ | このブランチの公式セキュリティ バージョンまたは完全な公式パッチ セットを使用してください | ブランチのマッチング、依存関係の補完、拡張機能の互換性、回帰の受け渡し |
| 7.4、8.0、8.1の対象 | ベンダーのバックポートを優先します。必要に応じて公式の緊急ソースコードブランチを評価する | 動作の変更を特定し、サポートされているバージョンへの移行をスケジュールする |
公式パッチがリリースされており、実際の修正はこれらのパッチから開始されるはずです。セクション 6 のコード スニペットは、設計とレビューの要点を説明することを目的としており、個別に適用できる完全なパッチを構成するものではありません。 S1 S4 S6
4. 正式な修理プロセス
4.1 実際にリクエストを処理するランタイムのインベントリ
少なくとも以下を記録するための簡単な台帳を作成することをお勧めします。
- エントリ ドメイン名またはサービス、リバース プロキシ バックエンド、PHP SAPI。
- PHP ブランチ、完全なパッケージ バージョンまたはイメージ ダイジェスト、ビルド ソース。
- FPM pool、実際のサービスユニット、コンテナ、または Pod、レプリカの数。
- 拡張機能、メイン設定ファイル、および追加の設定ファイルがロードされました。
- 直接アクセスできる他の PHP バージョン、古いデプロイメント コピー、またはオリジン ポータルはありますか?
これらは、「アップグレード」が実際の各トラフィック エントリに対応できるようにするための実装提案です。特に、コマンド ライン PHP と Web PHP が異なるバージョンを使用していないか、イメージは構築されているが古いコンテナーがまだ実行中であるか、プールの一部またはコピーが置き換えられていないかなどを確認してください。
4.2 正しいアップデートを選択して展開してください
できれば既存の信頼できるパッケージ ソースまたは管理されたビルド チェーンを使用して、セクション 3 に従って修正バージョンを確認します。更新スコープには、FPM パッケージ、Apache PHP モジュール、CGI バイナリ、PHP が埋め込まれているサービス ビルドなど、実際にリクエストをホストするコンポーネントが含まれている必要があります。
アップグレードする前に、構成とパッケージのリストを保管し、運用環境と同様の環境で起動サービスと主要なサービスを確認してください。自己保守拡張機能の場合は、バージョン PHP に対応するビルドと実行の互換性を確認してください。別のブランチから一見関連すると思われるコミットを選択しただけでは、修正セット全体が実装されたことは保証されません。
4.3 実行中のインスタンスを再起動またはロールオーバーします
ファイルをインストールすることと、新しいコードをプロセスにロードすることは別のことです。対応するサービスを再起動するか、ローリング置換を完了し、古いワーカーと古いコンテナが終了したことを確認する必要があります。
mod_php の場合は、モジュールをホストしている Apache プロセスを再起動します。 PHP が埋め込まれているサービスでは、ホスティング プロセスを置き換える必要があります。 FPM の場合、OPcache をクリアしても、ランタイムの更新と古いワーカーの廃止は置き換えられません。
グレースフル スイッチングを使用する場合は、古い世代のプロセスがまだ長い接続や未処理のリクエストを処理しているかどうかを確認する必要があります。受け入れレコードには、実際のサービス、デプロイメントのバージョン、変更の完了時間、古いインスタンスの終了結果が含まれている必要があります。
4.4 実際の Web リクエストを通じて検証します
単一のバージョン コマンドだけに依存するのではなく、次の証拠を組み合わせることが推奨されます。
| 証拠 | 証明できること | 一人では何も証明できない |
|---|---|---|
| パッケージマネージャーまたはイメージメタデータ | インストールソースと完全なビルド | トラフィックはこのインスタンスに切り替えられました |
| プロセスと展開のステータス | 作業者またはコンテナが交換を完了 | 外部入口をそこにルーティングする必要があります |
| 実際のポータル経由でアクセスできる診断結果が制限されている | 実際の Web SAPI と実行コンフィギュレーション | リリース バックポートが 2 つの CVE をカバーするかどうか |
| ベンダーの発表または完全なパッチレコード | このバグ修正はこのビルドに含まれています | すべてのレプリカがデプロイされています |
PHP_VERSION、PHP_SAPI、ロードされた構成ファイル、および緊急構成は、既存の内部診断機能、またはアクセス制御された一時的な診断ポータルを通じてチェックできます。リクエストが CDN またはページ キャッシュによって直接返されないことを確認してください。完了したら、一時的な診断エントリを削除します。
php -v は通常、シェルによって現在選択されている CLI バイナリのみを示します。 php-fpm -i などのコマンドは、トラフィックを受信している既存のワーカーを確認することと同等ではありません。 phpinfo() ページ全体をパブリック ネットワークに長時間公開しないでください。
4.5 ビジネス回帰チェックと緊急設定の削除
この変更によって影響を受ける機能に関する通常のログイン、セッションの読み取りと書き込み、フォームとアップロード、インポート、エラー処理、およびワーカーの安定性を確認します。エラー率、応答遅延、メモリピーク、プロセス終了、リビルド頻度が異常でないか確認してください。
memory_limit=-1 が一時的に設定されている場合、公式パッチの適用後に、ビジネス能力に見合った限られた予算が復元されます。 pm.max_requests=1 が設定されている場合、修復が確認された後、容量評価されたライフ サイクル構成が復元されます。入力サイズ制限とソース アクセス制御は、ビジネス ニーズに応じて維持できます。
アップグレード中に互換性の問題が発生した場合は、影響を受けるポータルを一時停止するか、外部アクセスを制限するか、ロールバックする前にアプリケーションを調整することを優先する必要があります。修復されていないランタイムが再びパブリック ネットワークに直接サービスを提供できるようにすると、元のリスクが再び発生します。
5. すぐにアップグレードできない場合の緩和策
このセクションは、短期的な危険性の削減または可用性の向上を目的としています。各対策は特定のパスのみをカバーしており、複数の対策を組み合わせても完全な修復にはなりません。 S1 S2 S3
5.1 PHP よりも先にトラフィック制御を優先します
サービスが許可する場合は、PHP の前に、機密性の高いエンドポイントを信頼できるソースに一時的に制限するか、アクセス制御を強制します。アップロード ワークロードの場合、リクエスト本文のサイズ、フィールド数、パーツ数、パーツごとのヘッダー、およびネストの深さを制限します。マルチパートを必要としないサービスは、フロントエンドでマルチパートを拒否できます。 S2
これらの制限は、PHP へのすべての入り口をカバーするものです。 「upload」という名前の URL をインターセプトするだけでは、リクエスト本文内の PHP によって自動的に解析される他のエントリが失われます。チャンク転送、利用可能な宣言された長さの不足などの場合、制限は実際の読み取りサイズに基づく必要があります。アプリケーションは、コンテンツを再度解凍または展開するときに、独自の出力サイズ バジェットも持つ必要があります。
5.2 FPM pool 構成テンプレート
以下の設定を FPM pool 実際にリクエストを処理する構成セクション 、文字通りではありません php.ini 。 8M および 4M の値は、ワークロードに合わせて調整する例です。全体を制限する場合は、フォームフィールドとマルチパート境界のための余地を残しておきます。 POST リクエスト。 S11 S12
; Temporary mitigation: evaluate capacity before applying.
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 4M
php_admin_flag[session.upload_progress.enabled] = off
PHP 8.5 のみに加えて:
php_admin_flag[fatal_error_backtraces] = off
それぞれの機能と境界は次のとおりです。
| 構成 | 期待される効果 | 保持する必要がある制限事項の説明 |
|---|---|---|
memory_limit=-1 | 予測可能なPHPリクエストメモリ上限トリガー条件を削除 | 根本的な割り当てエラーを防ぐことはできません。元の予算をキャンセルすると、メモリ不足やサービス中断のリスクが高まる可能性があります。 |
小さい post_max_size | 解析プロセスに入るデータのサイズを削減する | 未修正のパーサーには既知のギャップがあります。メモリの増幅を単独で防ぐことはできない |
upload_max_filesize < post_max_size | 単一ファイルのサイズを制限し、リクエストのオーバーヘッド スペースを確保する | すべてのフィールド、メタデータ、またはアプリ内割り当てを制限するわけではありません |
| アップロードの進行状況を閉じる | 確認されたセッション関連のパスをブロックします | 他のグローバル状態のバリアントはカバーされません |
| PHP 8.5 致命的なバックトレースを閉じます | 確認済み関連ステータスのプロデューサーをブロックする | セッションなどの他のパスはカバーされません |
測定の境界は公式発表に基づいています。プールの構文と管理レベルの構成セマンティクスについては、 PHP マニュアル。 S1 S2 S3 S11
管理レベルの php_admin_* 設定は、アプリケーションによって ini_set() を介して上書きできません。すべてのプール、ディレクトリレベル、およびフロントエンドの受信構成をレビューして、実際のリクエストの値が期待どおりであることを確認する必要があります。変更後、既存のプロセスが古い状態を保持し続けるのを防ぐために、すべてのワーカーを再構築します。
php.ini を直接変更する場合は、構文を次のように変更する必要があります。
memory_limit = -1
post_max_size = 8M
upload_max_filesize = 4M
session.upload_progress.enabled = Off
とは異なり php_admin_value プールで、ただセッティングするだけ memory_limit=-1 で php.ini アプリが再度変更することを妨げるものではありません。フレームワーク、アプリケーション コード、およびその他の構成をチェックして、制限値がリセットされているかどうかを確認する必要があります。強制が必要な場合は、現在のポリシーに適切な管理レベルの設定を使用してください。 SAPI 実際の実効値を確認してください。 S11 S12
追加 fatal_error_backtraces = Off のためだけに PHP 8.5 。アプリケーションレベルを使用しないでください ini_set() アップロードの進行状況を無効にするための回避策であり、依存しないでください。 FPM .user.ini リクエストを解析する前に有効にします。 S1 S3
5.3 PHP メモリ制限を削除するコストを管理する
memory_limit=-1 は、未修正の環境に対する一時的なパス緩和策であり、長期的なデフォルト構成としてコピーしないでください。アプリケーションまたはリクエストが制御不能になると、ホストのメモリがより多く使用される可能性があります。したがって、使用する前に、同時実行数、ピーク時の単一ワーカー、および合計サービス容量を評価し、フロントエンド入力制限を導入する必要があります。 S2
コンテナーまたは cgroup のメモリ制限は可用性の境界を提供しますが、割り当てが決して失敗しないことを保証するものではありません。制限がトリガーされると、コンテナー全体、マスター、およびすべてのワーカーも終了される可能性があります。分離の粒度と終了戦略は展開と併せて評価する必要があり、これら 2 つの CVE を完全に保護するとは言えません。 S2
上記の戦略を RLIMIT_AS、RLIMIT_DATA、または対応するプロセスのアドレス空間制限に置き換えないでください。これらは、基礎となる割り当てが依然として問題のある OOM パスに直接失敗する可能性があります。 S2
5.4 Nginx 構成例
Nginx がリクエストを PHP-FPM に転送する展開に適用されます。実際のホスティング サービスの構成レベルで設定できます。
client_max_body_size 8m;
fastcgi_request_buffering on;
client_max_body_size リクエスト本文のサイズを制限します。 fastcgi_request_buffering on しましょう Nginx まず完全なリクエスト本文を読み取り、それを FastCGI バックエンドに送信します。特定の場合に効果があるかどうか server または location 既存の継承およびカバレッジ関係と併せてチェックする必要があります。 S13 S14
ビジネスでマルチパートが必要ない場合のみ、対応するサービス エントランスに拒否ルールを追加できます。
if ($http_content_type ~* "multipart/form-data") {
return 403;
}
これは、if および return を使用した単純なエントリ制限テンプレートであり、パーサーの脆弱性に対する一般的なフィルタリング ルールではありません。デプロイ前に構成構文と通常のリクエストを確認し、カスタム error_page が 403 リクエストを PHP にリダイレクトするかどうかを確認します。文字列の一致は、すべての解析の違いを完全に保証するものではありません。 S15
さらに、これらの構成では、アプリケーションによって解凍できるデータ量、フィールド数、または PHP オブジェクトの数が自動的に制限されません。アップロードする必要がある企業は、リクエストの構造を理解した追加の制限を適用する必要があります。
5.5 オプションの軽減策: FPM ワーカーごとに 1 つのリクエスト
オーバーヘッドに余裕のある FPM 展開の場合は、短期セットアップを評価できます。
pm.max_requests = 1
そして、既存のワーカーを再構築します。これにより、前述のクロスリクエスト チェーンがワーカー再利用レベルでブロックされますが、プロセスの作成と初期化のオーバーヘッドが増加します。同時に、同じリクエストを修復することはできません OOM およびクリーンアップの問題 CVE-2026-109618 。値が小さいが 1 より大きい場合、リクエストの再利用ウィンドウはまだ存在します。 S3 S11
5.6 WAF および Cloudflare のカバレッジ制限
Cloudflare は、Free プランを含む、PHP2Shell に対する保護のための展開計画を発表しました。そのサービスを使用するときは、実際のトラフィックがプロキシを通過するかどうか、保護ルールが有効かどうか、発信元サイトを直接バイパスできるかどうかを確認する必要があります。有料プランの場合は、対応する管理ルールの構成と例外も確認する必要があります。 S16
ベンダーが説明している検出の一部は応答信号を利用しているため、すべての保護を「PHP に到達する前にすべての攻撃がブロックされる」と解釈することはできません。 WAF は被曝を軽減し、観測情報を提供するのに役立ちますが、PHP への継続的なアップグレードが依然として必要です。 S16
5.7 共通の対策が不十分な理由
| 対策とか判断とか | 欠点 |
|---|---|
file_uploadsのみを閉じてください | すべてのマルチパート処理をカバーできず、独自の OOM パスを適用できません |
enable_post_data_reading=Offの設定 | POST/FILES を自動的に埋める動作を変更します。リクエスト本文はアプリケーションによって引き続き読み取られる可能性があり、通常のビジネスが中断される可能性があります。 |
エラー表示をオフにし、ログに記録するか、@ を使用します。 | 内部診断処理が依然としてダングリング状態にアクセスする可能性がある |
| 労働者の量を増やす | 安全な状態のクリーンアップメカニズムを確立せず、単一ワーカーの再利用を排除しない |
disable_functions または open_basedir のみを構成します | これらの制限では、C エンジン層のメモリ破損は修正されません |
| バージョンまたは 1 つのコピーを 1 回だけチェックしてください | すべての入口と実行中のインスタンスが置き換えられたことを証明することはできません |
| 例外ログは表示されません | 脆弱性が存在しないこと、またはこれまでに悪用されていないことを証明することはできません。 |
その中で、構成と脆弱性メカニズムの基礎は、 PHP で見つけることができます S2 S3 S12 ;適用範囲、承認、および許可の境界に関する判断は、これらのメカニズムによって提案された実装提案に基づいています。
6. 公式パッチの実装アイデアと検討ポイント
6.1 正しいブランチに完全な修正を使用してください
PHP 8.5 の代表的な公式提出物は次のとおりです。
31c0ea7d7ff1d1fccb6492e52dab544011628065
Avoid state corruption via bailout
このコミットは、OOM 終了メカニズムを調整し、初期化フェーズ中にアクセスされる可能性のあるグローバル状態を修正するために、2 つの CVE を明示的に関連付けます。完全な差分を含むページを送信します (S4S5 を参照)。他のブランチは独自の公式セキュリティ リリースまたは一致するパッチを使用する必要があり、8.5 への変更が古いバージョンに直接適用できるとは想定できません。
6.2 OOM 修復: まず処理可能な状態に復元してから、リクエストを終了します
正式な実装では、ソフトとハードの 2 つのレベルが導入されます。 OOM 処理: ソフト リミットに達すると、保留ステータスが記録され、制御された終了が次のような安全な場所で実行されます。 VM ;失敗可能な割り当てインターフェイスにより、呼び出し元は失敗を明示的に処理できます。失敗を直接返すことができない割り当ての場合、より高いハードしきい値を超えることが予想される場合、安全でない中間状態でリクエストの処理が続行されることを避けるために、プロセスは直接終了されます。 S2 S5
以下は、保留中の OOM をマークするために使用される 8.5 diff のキー コードの抜粋です。
EG(delayed_oom).state = ZEND_OOM_STATE_PENDING;
zend_atomic_bool_store_ex(&EG(vm_interrupt), true);
VM 割り込み処理とその他の安全な場所は、その後 zend_handle_delayed_oom() を呼び出します。そのユーザー コード実行コンテキストは、制御されたアンワインド パスを使用します。ハード OOM パスは _exit(137) を呼び出します。 S5
設計の観点から見ると、重要な変更点は次のとおりです。 は、構造が中間状態にあるときに C 呼び出しスタックを任意に横断することを回避し、状態制約を維持できる位置 に出口を配置します。ソフト制限がトリガーされた後、プロセスを完了するために追加のメモリが必要になる場合があるため、新しいソフトしきい値はプロセスの合計メモリの絶対的な上限として理解できません。
また、「PHP がすべての zend_bailout() を削除した」と要約することもできません。このパッチは引き続き、特定のコンテキストで関連するメカニズムを使用します。修正されるのは、危険な終了タイミングとそれに伴う状態管理です。 S5
6.3 割り当て呼び出し元とマルチパート解析を一緒に更新します
割り当て関数を「失敗時に NULL を返す」ように変更しただけで、元の呼び出し元が依然として有効なポインターが常に返されると想定している場合、新しい NULL ポインター アクセスまたは不完全なクリーンアップが発生することになります。パッチ内の失敗可能な割り当てインターフェイスは、呼び出し元のチェックと例外の伝播とともにレビューする必要があります。 S5
マルチパート関連の修正には、実際の読み取り量に基づいた累積チェックの実行、無駄なヘッダーまたは重複したヘッダーの処理の削減、OOM が保留中の場合の一貫した終了およびクリーンアップ ロジックの採用も含まれます。これらの変更により、リソースの増大が削減され、パーサーが新しい OOM プロトコルに準拠するようになります。 S5
独自のブランチを維持するチームの場合、コード レビューの焦点を次の問題にすることをお勧めします。
- 完全に初期化される前に、その状態は外部から見えるのでしょうか?
- 割り当ての失敗またはコールバック例外の後でも、所有権は依然として一意であり、明確ですか?
- 途中で失敗した場合、統合クリーンアップ出口に到達できますか?
- クリーンアップ関数は初期化されていないフィールドまたは解放されたフィールドを認識できますか?
- 解析予算は信頼リクエストの要求だけでなく、実際の処理量に基づいていますか?
- 新しい失敗の戻り値はすべての呼び出し元によって処理されましたか?
これらは、修正メカニズムに基づいて要約されたレビュー質問であり、提供されていないコード ベースに対して完了した監査の結論ではありません。
6.4 クロスリクエストの修正: 初期化が早く、最終クリーンアップが後で
CVE-2026-109619 に対応するパッチは、複数のライフサイクル境界を同時に調整します。以下にリストされているファイルと操作は、PHP 8.5 公式 diff を例として取り上げています。 S5
| 場所 | 方向を変える | 問題は解決しました |
|---|---|---|
Zend/zend_execute_API.cなど | エラー、例外、ハンドラ、オブジェクトなどのエグゼキュータのステータスをリセットします。 | リクエストが終了した後も、次のリクエストでアクセスできる古い参照が残ります。 |
main/main.c の起動パス | SAPI がアクティブになる前に php_basic_early_rinit() を呼び出します | 初期のコンシューマが発生したとき、関連する基礎となる状態はまだ初期化されていません。 |
main/main.c のパスを閉じる | HTTP globals を破棄し、未定義としてマークします | 解放された値は引き続き有効なオブジェクトとみなされます |
| リクエスト ヒープが最終的に解放される前に | 最後のエラーメッセージを再度クリーンアップします | 遅延クリーンアップ診断によりエラー ステータスが再設定されます |
ext/session/session.c | アップロードの進行状況 初期パスが初期化される 最初のセッション グローバル | 通常モジュール RINIT は以前に古い状態にアクセスしました |
| シリアル化関連のコード | 初期処理におけるクラス解析とユーザー コールバックを制限する | 初期化が完了していない場合に追加のユーザーコードを実行する |
たとえば、起動シーケンスには次のものが含まれます。
zend_activate();
php_basic_early_rinit();
sapi_activate();
HTTP globals が破棄された後、ステータス失敗マークを追加します。
zval_ptr_dtor(&PG(http_globals)[i]);
ZVAL_UNDEF(&PG(http_globals)[i]);
これらの抜粋は 2 つの原則を示しています。可能な限り最も早いコンシューマーの前に初期化し、状態を再作成する可能性のある最後の操作の後に最終クリーンアップを実行します。 通常の RINIT または以前のシャットダウン段階中にのみポインターをリセットすると、それ以前または後のアクセスが失われる可能性があります。 S5
6.5 独自の「一行修復」を行うことが推奨されないのはなぜですか?
すべての zend_bailout() を _exit() に置き換えたり、特定のエントリに NULL ポインタ チェックを追加したりすると、多数の異なる実行コンテキストにまたがることになります。他のステータス フィールドを省略したり、破棄、拡張コールバック、プロセス ホスティング、および要求終了セマンティクスを変更したりする場合があります。
サポートされているバージョンでは、すでにリリースされている完全な修正が優先されます。独自のブランチの移行では、パッチのソース、適用可能なベースライン、競合処理と動作の変更を記録し、対応する上流回帰のユースケースとこのビジネス プロセスの検証を使用する必要があります。ここでの提案は、アロケータ全体にわたるパッチのスコープの分析から得られています。 VM 、セッションとリクエストのライフサイクルが変更されます。 S4 S5
7. PHP 7.4、8.0、8.1の緊急バックポート
PHP は、重大度に基づいて 3 つの古いブランチの最小限のソース コード バックポートを正式に提供します。ブランチ名は次のとおりです。
PHP-7.4-CVE-2026-109618-109619
PHP-8.0-CVE-2026-109618-109619
PHP-8.1-CVE-2026-109618-109619
ブランチリンクについては、を参照してください。 S7 S8 S9 。これらはこの脆弱性に対する緊急配信であり、古いブランチの通常のアップストリーム サポートへの復帰を意味するものではなく、他のセキュリティ更新プログラムを置き換えるものでもありません。 S1
7.1 PHP 8.1 バックポートを例にします
PHP 8.1 に関連する提出物は次のとおりです。
1d7dec178a094e6e75b229ce22754045f8c6070a
その戦略はフェイルファストを優先します。つまり、対応する OOM パスに診断を出力した後に _exit(1) を呼び出し、グローバル ステータスやその他の関連する修正を含めます。セッションアップロードの進行状況に対応する処理を内部的に無効にします。関連するソース コードの提出については、S6 を参照してください。
これは、サポートされるブランチのより完全な遅延 OOM デザインとは動作が異なります。設定ではアップロードの進行状況が依然としてオンであることが示されているからといって、このバックポート後の内部処理動作が変更されないことを意味するわけではありません。
7.2 導入時に受け入れる必要がある価格
プロセスを直接終了すると、現在のリクエストが失敗し、通常の PHP シャットダウン コールバックがスキップされ、アプリケーションの一部が終了する可能性があります。 if the host adopts a thread model, it is also necessary to evaluate the impact of the entire host process exit on other concurrent work.プロセス管理者が代替プロセスを時間内に引き上げられるかどうかも検証に含める必要があります。
したがって、古いバージョンのユーザーは次のことを順番に検討する必要があります。
- サポートされている PHP ブランチとその修正バージョンに移行します。
- CVE または LTS のメーカー アップデートの両方を明示的にカバーするリリースを使用してください。
- 実際に古いバージョンのソース コードの影響を受ける場合は、一致するバージョンの公式緊急バックポートを使用して、完全な変更と互換性を確認し、その後の移行を手配します。
ここでの「最小限のバックポート」は、公式が選択した互換性と実装範囲を説明するものであり、「既知の不完全な脆弱性修正」として自動的に解釈されるべきではありません。対応するブランチのソースコードやメーカーの発表に基づいて判断し、対応する変更を自分で削除しないでください。 S1 S6
8. 合否基準と事後検査
この修復を完了するための基礎として、次の結果を使用することをお勧めします。
| 受入品目 | 完了基準 |
|---|---|
| 脆弱性の範囲 | ビルドまたはベンダーの発表により、CVE-2026-109618 および CVE-2026-109619 が明示的に修正されました |
| 導入範囲 | すべてのポータル、プール、サービス、レプリカは修復されたランタイムを使用します |
| プロセスが有効になる | 古いワーカー、古いホストプロセス、古いコンテナはすべて終了します |
| 本物のリクエストの検証 | SAPI を確認し、キャッシュのミスダイレクトを排除するために実際の Web リンクを構築および構成しました |
| ビジネスの可用性 | セッション、アップロード、インポート、エラー処理などの主要な機能が正常に戻りました。 |
| 臨時措置の終了 | 無制限のメモリとエクストリーム ワーカー リサイクル構成が容量計画に従って復元されているか、保持する明確な理由がある |
| 変化の証拠 | パッケージのバージョンまたはイメージのダイジェスト、更新範囲、完了時間、検証結果を記録します。 |
上記は実装のための提案です。 OOM の動作、異常終了、またはカスタム パッチを検証する必要がある場合は、受け入れ方法として運用環境で繰り返しメモリ枯渇が発生することを避けるために、分離された環境でアップストリーム回帰テストまたは制御されたフォールト インジェクションを使用する必要があります。
Also check the PHP fatal, worker crash, abnormal restart, request error rate and WAF events before and after the update.ログは調査の手がかりのみを提供します。OOM の発生は悪用されたことを意味するものではなく、アラームがないことは悪用が発生していないことを証明するものではありません。アップグレードにより、将来到達する可能性のある脆弱性パスが修正されます。 if anomalies such as file tampering or credential leakage are found, separate incident investigations should be carried out.
付録: 引用元とリンク
すべてのソースリンクは以下にまとめられています。 The advisories, patches, and vendor guidance reflect checks as of October 22, 2026; subsequent deployments should check for vendor updates. The numbered citations in the text refer to these entries.
S1 — PHP 公式セキュリティ情報および修復バージョン
- 出典: プロジェクト PHP、2026 年 10 月 21 日。
- 目的: リスク範囲、4 つの公式修復バージョン、公式の一時措置、および古いブランチに対する緊急バックポート手順。
- 参照: PHP 2026 This security bulletin は年次速報アーカイブにあります
S2 — CVE-2026-109618 公式技術速報
- 出典: php/php-src GitHub Security Advisory、2026 年 10 月 21 日。
- 識別: GHSA-w8hw-w9fx-j79w。
- 目的: OOM のカバレッジ境界、マルチパート増幅、SAPI の差分および緩和。
- 参照: RCE via OOM corruption
S3 — CVE-2026-109619 公式技術速報
- 出典: php/php-src GitHub Security Advisory、2026 年 10 月 21 日。
- 識別: GHSA-6wmf-4rv5-p3rp。
- 目的: クロスリクエストのダングリング状態、プロデューサーとコンシューマー、早期の初期化、構成の軽減。
- 参照: RCE via stale global state
S4 — PHP 8.5 公式修正の提出
- 出典: php/php-src。
- 送信:
31c0ea7d7ff1d1fccb6492e52dab544011628065。 - 目的: 2 つの脆弱性を同時に修正するための正式な提出を確認し、全体的な変更の方向性を説明します。
- 参照: Avoid state corruption via bailout
S5 — PHP 8.5 正式に復元され完全な差分
- 出典: 同じ公式提出からの差分。
- 目的: アロケーター、VM、HTTP globals、セッション、シリアル化、およびリクエストのライフサイクルの特定の実装を確認します。
- 参照: official complete diff
S6 — PHP 8.1 公式緊急バックポート提出
- 出典: php/php-src。
- 送信:
1d7dec178a094e6e75b229ce22754045f8c6070a。 - 目的: 古いブランチの迅速な終了を確認し、進行状況の動作の変更をアップロードします。
- 参照: PHP 8.1 Emergency backport submission
- 参照: corresponds to complete diff
S7 — PHP 7.4 公式緊急バックポート ブランチ
- 出典: 公式セキュリティ情報に記載されている php/php-src、PHP ソース コード ブランチ。
- 参照: PHP-7.4-CVE-2026-109618-109619
S8 — PHP 8.0 公式緊急バックポート ブランチ
- 出典: 公式セキュリティ情報に記載されている php/php-src、PHP ソース コード ブランチ。
- 参照: PHP-8.0-CVE-2026-109618-109619
S9 — PHP 8.1 公式緊急バックポート ブランチ
- 出典: 公式セキュリティ情報に記載されている php/php-src、PHP ソース コード ブランチ。
- 参照: PHP-8.1-CVE-2026-109618-109619
S10 — Ubuntu セキュリティ情報 USN-8948-1
- 出典: Canonical / Ubuntu、2026 年 10 月 21 日。
- 目的: バックポートと完全なパッケージ バージョンのサンプルをリリースします。
- 参照: USN-8948-1: PHP vulnerabilities
S11 — PHP-FPM Configuration マニュアル
- 出典: PHP 公式ドキュメント。
- 目的:
php_admin_value、php_admin_flag、pm.max_requestsなどの構成セマンティクス。 - 参照: PHP-FPM Configuration
S12 — PHP コア INI 構成マニュアル
- 出典: PHP 公式ドキュメント。
- 目的: リクエスト本文、アップロード、メモリ、自動 POST 読み取り構成の定義と範囲。
- 参照: Description of core php.ini directives
S13 — Nginx リクエスト本文のサイズ制限
- 出典: Nginx 公式ドキュメント。
- 目的:
client_max_body_sizeの意味と利用可能な構成レベル。 - 参照: ngx_http_core_module / client_max_body_size
S14 — Nginx FastCGI リクエスト バッファ
- 出典: Nginx 公式ドキュメント。
- 目的:
fastcgi_request_bufferingの処理シーケンスと機能。 - 参照: ngx_http_fastcgi_module / fastcgi_request_buffering
S15 — Nginx 条件および戻り命令
- 出典: Nginx 公式ドキュメント。
- 目的:
ifおよびreturnの構成構文。 - 参照: ngx_http_rewrite_module
S16 — Cloudflare PHP2Shell 保護命令
- 出典:Cloudflare公式ブログ。
- 目的: WAF の展開範囲、Free 計画の配置と検出メカニズムの説明。
- 参照: Cloudflare deploys protections against php2shell vulnerability