PHP2Shellは、PHP本体にある2つの重大な脆弱性、CVE-2026-109618とCVE-2026-109619です。Webリクエストを処理するあらゆるPHPインストール(PHP-FPM、mod_phpを使うApache、php-cgi、FrankenPHP、LiteSpeed)で、認証不要のWebリクエストによるコード実行を許すおそれがあります。どちらも実際に悪用されており、CISAのKEVカタログに掲載されています。修正はPHP 8.5.12、8.4.27、8.3.36、8.2.35で、PHP 8.1以前にはアップストリームのリリースがありません。アップグレードしたうえで、PHPを含むすべてのコンテナイメージを再ビルドして再デプロイしてください。今も稼働している古いタグや、顧客に出荷したイメージも対象です。
把握しているサーバーへのパッチ適用は簡単な部分です。長く残るのは、忘れているPHPです。ベースイメージにコンパイルされたランタイム、本番環境でまだ動いている昨年のイメージタグ、CIのイメージ、サポート終了のPHPを含んだまま顧客に出荷した製品などです。このページでは、まずパッチを適用し、そのあとで残りを見つける方法を説明します。
何が起きたか
| 日付(2026年) | 出来事 | 出典 |
|---|---|---|
| 8月11日と21日 | CalifがPHPプロジェクトに2つのバグを報告 | Calif |
| 10月17日 | Amazonがハニーポットで最初に観測した悪用の試み(公表前) | Amazon Threat Intelligence |
| 10月20日 | PHPが、CVSS 4.0で9.2と評価された2つの脆弱性を修正するセキュリティリリースを10月21日14:00 UTCに行うと告知 | php.net |
| 10月21日 | PHPが8.5.12、8.4.27、8.3.36、8.2.35をリリースしてアドバイザリを公開。CVEレコードが公開され、NCSC-NLがphp2shellリポジトリを開設 | PHPのアドバイザリ、NCSC-NL |
| 10月21日 | Docker公式のphpイメージが修正バージョンに更新 | docker-library/php |
| 10月21日 | watchTowrが両CVEの実際の悪用を報告し、CISAがアラートを公開 | watchTowr、CISA |
| 10月22日 | Searchlight Cyberがphp2shell-scannerを公開 | GitHub |
| 10月23日 | PHPが、可能性は低い別のRCEの経路CVE-2026-115560に対してsession.upload_progress.enabled=0の設定を推奨 | php.net |
| 10月26日 | CISAが両CVEをKEVカタログに追加。米国連邦機関の対応期限は10月29日 | CISA KEV |
PHP2Shellという名前はCalifの解説記事に由来し、業界の報道で広く使われていますが、PHP自身のアドバイザリでは使われていません。CVEレコードでは、Calif、Wiz、OpenAIが発見者としてクレジットされています。
影響を受ける対象
Webリクエストを処理するすべてのPHPです。PHPのアドバイザリは、PHP-FPM、mod_phpを使うApache、php-cgi、FrankenPHP、LiteSpeedを挙げ、リスクが最も高いのはmod_phpだとしています。「認証不要のリクエストが、アプリケーションコードが実行される前に攻撃を引き起こせることを示すエクスプロイトが実証されています」。バグはPHP本体にあるため、Laravel、Symfony、WordPressで構築されたアプリケーションも、その下で動くPHPが影響を受ける限り露出しています。
| ブランチ | 影響を受けるバージョン | 修正バージョン | アップストリームのサポート |
|---|---|---|---|
| 8.5 | 8.5.12より前 | 8.5.12 | アクティブ |
| 8.4 | 8.4.27より前 | 8.4.27 | アクティブ |
| 8.3 | 8.3.36より前 | 8.3.36 | セキュリティ修正のみ(2027年12月31日まで) |
| 8.2 | 8.2.35より前 | 8.2.35 | セキュリティ修正のみ(2026年12月31日まで) |
| 8.1、8.0、7.4 | 全バージョン(CalifとwatchTowrの報告による) | リリースなし。php-srcに最小限のソースのバックポートあり | サポート終了 |
| 7.3以前(PHP 5を含む) | 全バージョン(CalifとwatchTowrの報告による) | アップストリームの修正なし | サポート終了 |
PHPのアドバイザリが挙げているのはサポート中のブランチだけです。それより古いブランチについて、Califは「私たちが見つけた最も古い影響を受けるパスはPHP 5.4.0にさかのぼります」と報告し、watchTowrはPHP 7とPHP 5を修正なしで影響を受けるものとしています。PHPは、8.1以前のブランチは「PHPプロジェクトから更新を受け取らなくなっています」としていますが、ソースからビルドする人向けに7.4、8.0、8.1の最小限のソースのバックポートを公開しました。一部のディストリビューションや商用の長期サポートベンダーは、サポート終了のブランチ向けにバックポートした修正を提供しています。利用先に問い合わせてください。次のメジャーバージョンをテストしている場合、同じ日にリリースされたPHP 8.6.0 RC4にも修正が含まれています。
仕組み
どちらのCVEも、PHPがリクエストを準備し、後片付けする処理にあるメモリ安全性のバグで、アプリケーションコードより下の層にあります。CVEレコードは両方を解放後使用(CWE-416)に分類し、あわせて例外的な状況の不適切な処理、初期化されていないポインタへのアクセス、制御されないメモリ割り当て、不正な初期化(CWE-755、CWE-824、CWE-1325、CWE-1419)にも分類しています。PHPの説明は次のとおりです。
- CVE-2026-109618、OOM破損によるRCE:「メモリ不足の処理によって、内部のリクエストデータが部分的にしか初期化されていない状態でPHPが中断されることがあります。その後、リクエストのクリーンアップが無効なデータを有効なものとして扱う可能性があります。」PHPが解析する間にメモリを使い果たすよう作られたリクエストボディが、この中断を引き起こします。mod_phpを使うApacheはリクエストの開始処理が失敗してもクリーンアップを実行するため、そこではアプリケーションコードが動く前に攻撃が成立します。PHP-FPMについては、PHPのアドバイザリが、ソースの分析から影響を受けやすいと考えられるものの、FPMに対する完全なエクスプロイトは実証されていないとしています。
- CVE-2026-109619、古いグローバル状態によるRCE:「リクエストが所有する内部状態が、その裏付けとなるメモリが解放された後も残ることがあります。同じワーカーが処理する後続のリクエストが、通常の初期化でリセットされる前にその古い状態を使う可能性があります。」同じワーカーに届く2つのリクエストが必要です。致命的エラーなどで状態を残すリクエストと、それを使うリクエストです。PHPのアドバイザリは、セッションのアップロード進捗の経路をmod_phpとFPMで、PHP 8.5の致命的エラーのバックトレースの経路をmod_phpで確認しています。
PHPの暫定設定がメモリ制限、リクエストボディのサイズ、セッションのアップロード進捗、致命的エラーのバックトレースを対象にしているのはこのためです。それぞれがバグそのものではなく、バグに至る経路を1つずつ塞ぎます。CNAであるPHPは、CVSS 4.0で両方を9.2と評価しています。NVD独自のCVSS 3.1の評価は、CVE-2026-109618が9.8、CVE-2026-109619が8.1です。
影響を受けているかの確認方法
把握しているホストから始め、次にビルドして出荷するすべてのものからPHPを探します。
ホストやVMでは、PHPが報告するバージョンを確認します。php-fpmやApacheモジュールはコマンドラインとは別のパッケージから来ていることがあるため、WebのSAPIも確認してください。
php -v
php-fpm -v
ディストリビューションのパッケージ(Debian、Ubuntu、Alpine、RHEL)は、アップストリームの新しいバージョンなしにバックポートとして修正を受け取ることがよくあります。たとえばUbuntu 24.04は修正を8.3.6-0ubuntu0.24.04.13として出荷しています。この場合、バージョンの確認だけでは判断を誤ります。インストール済みのパッケージを一覧表示し、ディストリビューションのセキュリティトラッカーにある修正済みパッケージのバージョンと比較してください。
dpkg -l 'php*' | grep '^ii' # Debian, Ubuntu
apk info -v | grep '^php' # Alpine
rpm -qa 'php*' # RHEL, Fedora, Rocky, Alma
コンテナイメージでは、公式のphp:イメージはPHPをソースからコンパイルするため、バージョンはディストリビューションのパッケージリストではなくイメージ自体の中にあります。イメージに直接問い合わせてください。
docker run --rm --entrypoint php php:8.3-fpm -v
実際に動かしているすべてのイメージを確認するには、一覧を取得して1つずつ問い合わせます。Kubernetesの場合は次のとおりです。
kubectl get pods -A \
-o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \
| sort -u \
| while read -r image; do
version=$(docker run --rm --entrypoint php "$image" -r 'echo PHP_VERSION;' 2>/dev/null)
printf '%s\t%s\n' "${version:-no php}" "$image"
done
FROM debianやFROM alpineでビルドし、パッケージマネージャーでPHPをインストールしたイメージには、上記のパッケージの確認をイメージ内で実行する必要があります。
リポジトリでは、PHPを選択しているすべての箇所を検索します。
git grep -nE '^FROM[[:space:]]+(.*/)?php:' -- '*Dockerfile*' '*.dockerfile'
git grep -nE 'php-version|image:.*php' -- .github/workflows '*.yml' '*.yaml'
php:8.3.30-fpmのような固定タグは、誰かが変更するまで脆弱なままです。php:8.3-fpmのような可変タグは10月21日から修正バージョンで再ビルドされていますが、それ以前にビルドしたイメージは、再ビルドするまで古いPHPのままです。php制約(composer.json内)は、コードが受け入れるバージョンを示すもので、実際に動いているバージョンを示すものではありません。
CIでは、ビルドやテストのジョブが独自のPHPを使っていることがよくあります。php:のサービスコンテナ、php-version入力を持つセットアップアクション、ランナーのイメージなどです。これらは本番のトラフィックを処理しませんが、パイプラインがどのイメージとバージョンを生成しているかを示します。
公開されているホスト。 Searchlight Cyberのphp2shell-scannerは、パスごとに約29 MiBの大きなマルチパートリクエストでURLを調べます。テストする権限のあるホストに対してのみ実行してください。READMEは、memory_limitが低いパッチ適用済みのPHPで誤検知が出ること、またPHPがバージョンを開示しない場合、スキャナーはパッチ適用済みのサーバーと脆弱なサーバーを区別できないことを警告しています。証拠ではなく手がかりとして扱ってください。NCSC-NLのリポジトリには、検出ルールと、PHPを同梱する製品の一覧とそのステータスがまとめられています。
今日のスキャンでわからないこと。 レジストリ内のイメージを今日スキャンしてわかるのは、今日デプロイするものです。以前に顧客に出荷したリリース、顧客がまだ動かしている古いタグ、どのビルドが脆弱なPHPを含むイメージを生成したかはわかりません。それには、各ビルドに何が入ったかをリリースごとに記録したものが必要です。影響はあるか?新しいCVEをビルド全体で評価する方法をご覧ください。
修正方法と、まだパッチを適用できない場合の対処
- アップグレードする。 8.5.12、8.4.27、8.3.36、8.2.35、またはディストリビューションの修正済みパッケージにアップグレードします。8.1以前の場合はサポート中のブランチに移行してください。PHPのバックポートやベンダーのビルドは一時しのぎです。
- すべてのイメージを再ビルドする。 修正済みのベースから(ベースイメージを再度プルするか、キャッシュなしでビルドして)再ビルドし、再デプロイします。すでに動いているイメージは置き換えられるまで古いPHPのままなので、ワークロードも再起動してください。
- 検証する。 新しいイメージだけでなく、実行中のコンテナに対して、下のチェックリストで確認します。
まだアップグレードできない場合、PHPのアドバイザリは「特定の攻撃経路への露出を減らしますが、インストールを安全にするものではない」措置を挙げています。CVE-2026-109618については次のとおりです。
- 「
memory_limit=-1を設定してください。できれば、FPMプールやApacheの設定でのphp_admin_valueなど、アプリケーションが上書きできない方法で設定し、プール、ディレクトリ、アプリケーションのどの設定も有限の上限を戻していないことを確認してください。」 - 「ファイルのアップロードを必要としないアプリケーションでは、
post_max_size = 8Mを設定してください。ファイルのアップロードが必要な場合は、post_max_size = 32Mを設定してください。upload_max_filesizeはpost_max_sizeより小さくしてください。」 - 可用性の境界としてコンテナまたはcgroupのメモリ制限を使い、
RLIMIT_ASやRLIMIT_DATAで代用しないでください。「これらは脆弱なメモリ割り当ての失敗を引き起こす可能性があるため」です。
CVE-2026-109619については次のとおりです。
- 「
session.upload_progress.enabled=0を設定し、すべてのワーカーを再起動してください。php.ini、FPMプール、またはリクエストの解析前に適用されるサーバー設定を使ってください。ini_set()やFPMの.user.iniに頼らないでください。」 - 「PHP 8.5では、
fatal_error_backtraces=0を設定し、すべてのワーカーを再起動してください。」
各ワーカーが実際にどの設定で動いているかを確認します。
php-fpm -i | grep -E 'memory_limit|post_max_size|session.upload_progress.enabled'
CISAのアラートはさらに踏み込み、すぐに更新できない組織や、PHP 8.1以前をまだ運用している組織は「パッチの適用または更新ができるまで、PHPベースのシステムをオフラインにすべきです」としています。また、シェルを起動したりツールをダウンロードしたりするPHPのワーカープロセスを監視するよう勧めています。
修正の検証
- デプロイしたつもりのイメージではなく、実行中のPHPに問い合わせる。 実行中の各コンテナ内と各ホストで
php-fpm -v(またはphp -v)を実行し、8.5.12、8.4.27、8.3.36、8.2.35以降であることを確認します。 - ディストリビューションのパッケージでは、バージョン文字列だけを信用しない。 Debian、Ubuntu、RHELなどのディストリビューションは、すでに出荷しているバージョンに修正をバックポートするため、パッチ適用済みのPHPでも8.3.6と表示されることがあります。Ubuntu 24.04の修正は
8.3.6-0ubuntu0.24.04.13です。パッケージの完全なバージョンをディストリビューションのセキュリティトラッカーと比較するか、パッケージの変更履歴でCVEを探してください。通常はCVEが記載されています。逆方向の落とし穴もあります。アップストリームのバージョン番号だけを比較するスキャナーは、バックポート済みのパッケージを脆弱と判定することがあります。 - すべてのワークロードが再ビルドしたイメージで動いていることを確認する。 タグが修正済みのイメージを指すようになっても、古いイメージをプルしたPodは変わりません。各コンテナが動かしているイメージのダイジェストを、ビルドしたダイジェストと比較してください。
kubectl get pods -A \
-o jsonpath='{range .items[*]}{range .status.containerStatuses[*]}{.image}{"\t"}{.imageID}{"\n"}{end}{end}'
- すべてのワーカーが再起動したことを確認する。 PHP-FPMとApacheは再起動するまで古いコードを読み込んだままです。「侵害の確認」にあるプロセスの確認で、まだ古いコードを動かしているものがわかります。
- まだ暫定設定に頼っている場合は、 上記の
php-fpm -iコマンドで各プールを確認し、すべての環境でアップグレードが終わるまで設定を維持してください。 - 確認方法の節にある棚卸しをもう一度実行する。 本番環境だけでなく、レジストリ、CIのイメージ、顧客が動かしているリリース全体が対象です。
侵害の確認
PHP2Shellは実際に悪用されており、Amazonは修正の4日前、2026年10月17日に最初の試みを観測しました。インターネットに公開されたPHPが、それ以降のいずれかの時点で、暫定設定なしに影響を受けるバージョンで動いていた場合は、確認してください。
露出の規模。 Malloryが10月20日に公開したShodanのバナー集計は、CybelAngelの報告によれば、PHPを示すインターネット公開ホストを224万台見つけました。バージョンを表示する約150万台のうち、883,717台(59%)が公式の修正のないブランチで動いています。これはホストの数で、脆弱性が確認されたシステムの数ではありません。バックポート済みのパッケージは古く見えてもパッチが適用されていることがあり、約74万台のホストはバージョンを隠しています。
PHPを同梱するアプライアンスや製品。 PHPは、アプライアンス、ネットワーク機器、管理インターフェース、ベンダー製品の中でも動いており、自分では更新できないことがあります。NCSC-NLの一覧は、2026年11月9日時点でこうした製品を968件追跡していました。修正済み205件、脆弱215件、調査中93件、実行環境次第240件、影響なし214件です。これらの製品は個別に確認し、ベンダーの更新が提供され次第適用してください。
修正が実際に動いていることを確かめる。 ホストやVMでは、アップグレード前に起動したPHP-FPM、php-cgi、Apacheのプロセスは古いコードを動かし続けます。その場合、メモリマップでは置き換えられたバイナリやlibphpが削除済みと表示されます。プロセスの起動時刻もアップグレードの時刻と比較してください。
for pid in $(pgrep -f 'php-fpm|php-cgi|apache2|httpd|frankenphp'); do
grep -qE '(php|libphp)[^/]*\(deleted\)' "/proc/$pid/maps" 2>/dev/null \
&& echo "PID $pid still runs a replaced PHP"
done
ps -o pid,lstart,args -p "$(pgrep -d, -f 'php-fpm|php-cgi|apache2|httpd|frankenphp')"
一次情報による侵害の痕跡:
- リクエスト: 文字列
PHP_SESSION_UPLOAD_PROGRESSを含むフォームアップロードのPOSTリクエスト。Amazon Threat Intelligenceが悪用の試みで観測したものです。Amazonは送信元アドレス(103.216.220.92、31.223.184.166、37.19.200.5、134.209.159.64、103.114.163.188、95.217.98.37)も挙げていますが、共有の匿名化インフラに属するものだと注記しています。一致したら調査し、証拠とはみなさないでください。 - プロセスとファイル: シェルを起動したりツールをダウンロードしたりするPHPのワーカープロセス(10月23日にSigmaの検出ルールを追加したCISAによる)、Webサーバー上の想定外のプロセス実行やファイル変更(Amazonによる)。
- ログ: Apache、PHP-FPM、リバースプロキシ、サービスのログで、スクリプトの実行前に繰り返される警告やコアエラー、致命的エラーや構文解析エラー、
Maximum execution time exceeded。PHPのアドバイザリは、「ログにエラーがないことは安全の証明ではありません」と付け加えています。
侵害を前提とすべきとき。 これらの痕跡が1つでも見つかった場合、または公開されたサーバーで緩和策なしに影響を受けるPHPが動いていて、ログから悪用を否定できない場合は、侵害されたものとして扱ってください。PHPは影響を、Webワーカーのアカウントとしてのリモートコード実行と説明しています。このアカウントは通常、アプリケーションの設定やシークレットを読み取れます。
ワーカーが読み取れたものをローテーションする。 環境変数や設定ファイルにあるデータベースのパスワード、APIキー、トークン、セッションやCookieに署名する鍵(とそれで署名されたセッション)、ホストで利用できるクラウドの認証情報です。新しいシークレットが侵害されたマシンに置かれないよう、ホストを再構築してからローテーションしてください。
クリーンアップではなく再構築する。 侵害されたホストやコンテナは既知の安全なイメージから置き換え、アップロードディレクトリ、キャッシュ、生成されたコードなど、ワーカーが書き込めたファイルは引き継がないでください。侵害されたホストで作られたイメージ、ビルドキャッシュ、成果物も再利用しないでください。
顧客への伝え方
PHPで動くソフトウェアを出荷しているなら、顧客から問い合わせが来ます。すべての答えがそろう前でも、バージョンと対応策で回答してください。調整して使える回答例です。
PHP2Shell(CVE-2026-109618、CVE-2026-109619)は、8.5.12、8.4.27、8.3.36、8.2.35より前のPHPと、それより古いすべてのPHPブランチに影響します。[製品]のバージョン[x~y]はPHP [バージョン]を同梱しており、影響を受けます。[日付]にリリースしたバージョン[z]はPHP [修正バージョン]を同梱しています。[z]にアップグレードしてください。すぐにアップグレードできない場合は、当社のアドバイザリ[リンク]にあるPHPの設定を適用し、アプリケーションへのネットワークアクセスを制限してください。[製品]のバージョン[a~b]は影響を受けません。[日付]までにこのお知らせを更新します。
まだ確認中であれば、そう伝え、いつ回答するかを伝えてください。第一報と各結果のテンプレートは、サプライチェーン攻撃後に顧客へどう回答するかをご覧ください。
CRACIの役割
CRACIはGitHub Actionsのジョブを実行し、ビルド中に各ジョブが取り込むもの(コンテナイメージ、aptやapkのパッケージ、Composerのパッケージなど)を記録し、過去のすべてのビルドをそのSBOMとともに保持します。CVEが公開されると、継続的な再評価によって、影響を受けるパッケージを含んでいた過去のビルドにフラグが立つため、今日のスキャンでわかることだけでなく、どのリリースがどれだけの期間露出していたかがわかります。ポリシーゲートで、特定のCVEを含むビルドをブロックすることもできます。
このインシデントでの限界が1つあります。公式のphp:イメージにコンパイルされたPHPは、パッケージのダウンロードとしてではなく、イメージの中に含まれて届きます。CRACIは各ビルドがプルしたイメージの参照を記録するため、PHPのパッケージに加えてphp:タグでもビルドを検索してください。
ビルド記録の詳細:ビルド時SBOM、DockerイメージのSBOM、コンテナスキャンが見落とすもの、CISA KEVカタログ、CVEの公開トレンド。その他のインシデント:すべての脆弱性。
このインシデント以外のPHPセキュリティについては、PHPセキュリティガイドをご覧ください。
出典と更新履歴
一次情報:
- PHP:2026年10月21日のセキュリティアドバイザリ、2026年10月23日の情報提供アドバイザリ、GHSA-w8hw-w9fx-j79w、GHSA-6wmf-4rv5-p3rp、サポート中のバージョン
- CVEレコード:CVE-2026-109618、CVE-2026-109619
- CISA:2026年10月21日のアラート、KEVカタログ
- NCSC-NL:php2shellリポジトリ
- NVD:CVE-2026-109618、CVE-2026-109619
- FIRST:EPSSスコア
調査と分析:
- Calif:PHP2Shell、2つのPHPリモート脆弱性の物語
- Amazon Threat Intelligence
- watchTowr
- Akamai
- CybelAngel
- Searchlight Cyber php2shell-scanner
更新履歴:
- 2026-11-11:ボックスにNVDのスコア、EPSS、CWEの分類、クレジット、最新の安全なバージョン、サポート終了日を追加し、PHP 8.6.0 RC4と、バグの仕組み、修正の検証、侵害の確認の各節を追加。
- 2026-11-11:初版公開。