PHP プロジェクトは 2026 年 10 月 21 日 (UTC)、php2shell と呼ばれる 2 件の重大な脆弱性の修正版を公開しました。どちらも認証なしでリモートコード実行 (RCE) につながり得る問題です。WordPress や Laravel のように、PHP で動く Web サイトを運用している組織は、サーバーの PHP が対象かを確かめる必要があります。
この記事は、php.net の告知 と、PHP の GitHub にある 2 件のアドバイザリ (GHSA-w8hw-w9fx-j79w・GHSA-6wmf-4rv5-p3rp) で確かめた内容に絞って整理します。攻撃の手順には踏み込まず、修正版、危険な環境、自社の確認、暫定策、更新後の確認の順に扱います。脆弱性を継続的に管理する運用の作り方は 情報システムの脆弱性管理を ISMS で回す にまとめています。
更新が唯一の確実な対策
PHP の公式は、修正版への更新を唯一の確実な対策としています。設定で入口を減らす暫定策はありますが、アドバイザリはどれも「それだけでは安全にならない」と書いています。
修正版は次の 4 つです。
| 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 |
| 8.2 | 8.2.35 より前 | 8.2.35 |
PHP 8.1 以前は公式サポートを終了しています。ただし今回、PHP チームは 7.4・8.0・8.1 向けに、ソースからビルドする人などのための最小限の修正も公開しました。通常のサポートが再開したわけではありません。また、PHP 8.2 は 2026 年 12 月 31 日に EOL を迎えます。
注意
公式の告知は、PHP を使うすべての人に「すぐ更新する」ことを強く勧めています。Web リクエストを処理する PHP が対象なので、まず自社で PHP が動いているサーバーの一覧を作ってください。
2 件の脆弱性は何が起きるのか
2 件とも、CVSS v4.0 のスコアは 9.2 です。どちらも認証は要りません。アドバイザリには、攻撃の成否が条件に左右されることを示す「攻撃の複雑さ: 高」が付いています。実証済みの環境があるため、条件が厳しいからといって安心はできません。
CVE-2026-109618: メモリ不足の処理が引き起こす破損
PHP はメモリ不足 (OOM) を検知すると、longjmp() で現在の処理から抜けます。リクエスト用のメモリの初期化が完了する前に、ほかの処理から参照できる場面があります。その段階でメモリ確保に失敗すると、初期化を途中で抜けたことが適切に処理されず、リクエストの終了処理が不正な状態のメモリを読み取ってしまいます。
メモリ不足を起こす経路として、アドバイザリは次を挙げています。
- 長さを宣言しない multipart リクエストが、
post_max_sizeの最初の検査を通り抜けて、データを送り続ける - multipart の各パートに、ヘッダーを際限なく付けられる
- 空のファイル欄は
max_file_uploadsに数えられないが、ファイルのメタデータの配列は作られる
修正では、メモリ不足で longjmp() を使うのをやめています。
CVE-2026-109619: 前のリクエストの状態が残る
もう 1 件は、PHP のワーカーが前のリクエストで確保したメモリを指したままの状態 (グローバル状態) を持ち続ける問題です。メモリが解放されたあとに、次のリクエストが初期化される前の処理でその状態を使うと、解放済みメモリへのアクセス (use-after-free) が起きます。攻撃が成立するには、前後のリクエストが同じワーカーに届く必要があります。
アドバイザリが確認済みとしている経路は 2 つです。
- PHP 8.5 で
fatal_error_backtracesが有効な環境。mod_php に対して RCE が実証されている - セッションのアップロード進捗 (session upload progress) の処理。mod_php と PHP-FPM の両方で確認されている
どの環境が危ないのか
公式の告知は、Web リクエストを処理するすべての PHP 環境を対象としています。PHP-FPM・Apache の mod_php・php-cgi・FrankenPHP・LiteSpeed が含まれます。そのうえで、アドバイザリは実証の範囲を区別して書いています。
| 実行環境 | CVE-2026-109618 の記載 | CVE-2026-109619 の記載 |
|---|---|---|
| Apache mod_php | 既定の制限のまま、認証なしの RCE を確認済み | PHP 8.5 の fatal_error_backtraces で RCE を確認済み。セッションのアップロード進捗も確認済み |
| PHP-FPM | ソースの分析では影響を受ける見込み。完全な攻撃は未実証 | セッションのアップロード進捗を確認済み |
| FrankenPHP | ソースの分析では影響を受ける見込み。アプリケーションに依存しない攻撃を受ける可能性が高い | 既定構成では早期の設定処理を通る経路は未確認。アプリケーションや拡張機能による別経路は否定できない |
| LSAPI | 攻撃は成立しそうだが、検証は未実施 | 初期化前に設定値を適用するため、条件次第で影響を受ける候補 |
実証されていない環境も、安全だと確認されたわけではありません。mod_php については、起動に失敗してもリクエストの終了処理が実行されるため、アプリケーションのコードが実行される前に不正な状態が処理される、とアドバイザリは説明しています。mod_php を使っている環境を、最優先で更新してください。
自社の PHP が対象かを確かめる
更新の前に、どのサーバーのどの PHP が Web を処理しているかを特定します。
Web を処理している PHP を特定する
php -v が示すのはコマンドライン用の PHP です。Apache が読み込む PHP や、PHP-FPM のバージョンとは別のことがあります。
# コマンドライン用の PHP
php -v
# Apache が mod_php を読み込んでいるか
apachectl -M | grep -i php
# PHP-FPM のバージョン
php-fpm -vサーバーが複数ある場合は、一覧表にします。共有レンタルサーバーのように PHP のバージョンを管理画面から選ぶ環境では、提供元の告知で対応状況を確かめてください。
バージョン番号だけで判断しない
ディストリビューションのパッケージは、バージョン番号を変えずに修正だけを取り込む (バックポートする) ことがあります。その場合、番号が 8.5.12 より小さくても修正済みのことがあります。逆に、番号だけを見て安心することもできません。
パッケージの changelog に CVE 番号が載っているかを確認する方法があります。
# Debian・Ubuntu 系
apt changelog php8.3-cli | grep -E "CVE-2026-10961[89]"
# RHEL 系
rpm -q --changelog php | grep -E "CVE-2026-10961[89]"パッケージ名は環境によって違います。ヒットしないときは、提供元のセキュリティ情報を直接見てください。Remi など外部リポジトリを使っている場合も、その提供元の告知とパッケージの更新履歴で、2 件とも修正されているかを確認してください。
OpenAI の確認用ツールでできること
OpenAI は、確認用のツール php2shell-checker を公開しています。リポジトリを取得したディレクトリで、次のコマンドを実行します。
# Web サイトを確認する
node phpcheck.js "https://example.com"このツールが見るのは、X-Powered-By と Server のヘッダーに出るバージョンだけです。リダイレクトは追わず、本文も読みません。結果は OK・POTENTIALLY VULNERABLE・UNKNOWN の 3 つで、ヘッダーを隠している環境では UNKNOWN になります。UNKNOWN は確認できなかったという結果で、更新済みを意味しません。README は、ヘッダーからバックポートの有無は分からず、OK でも実際のインストール状態を検証したことにはならないと説明しています。
したがって、このツールは「更新が必要なサイトを洗い出す」用途には向きますが、「安全の確認」には使えません。
更新できないときの暫定策
更新に時間がかかる事情はあります。アプリケーションの検証、保守契約の確認、レンタルサーバーの対応待ちなどです。その間に取れる設定を、アドバイザリの記載に沿って整理します。
| 設定・対応 | 狙い | 限界 |
|---|---|---|
session.upload_progress.enabled=0 | セッションのアップロード進捗を経由する経路を止める (109619) | 進捗を経由しない経路は残る |
fatal_error_backtraces=0 (PHP 8.5) | 確認済みの RCE の入口を除く (109619) | 確認済みの入口が 1 つ減るだけ |
memory_limit=-1 を管理者設定で強制 | PHP がメモリ不足を検知する場面を減らす (109618) | mmap() の失敗では longjmp() に至る場合がある |
post_max_size を絞り、フロントで本文の大きさを制限 | 巨大なリクエストを入口で止める (109618) | 限界は上の設定と同じ |
| multipart の遮断、ネスト上限や項目数の制限 | 攻撃に使われる入力を制限する (109618) | アプリケーションが multipart を使うなら遮断できない |
cgroup の memory.max による制限 | メモリ不足をカーネル側で扱う。ワーカーごとに分けるのが望ましい | 部分的な代替 |
避けたい設定もあります。RLIMIT_AS と RLIMIT_DATA は、mmap() の失敗を起こすため、脆弱な経路に入りやすくなるとアドバイザリは書いています。
memory_limit=-1 は、PHP が使うメモリの上限を外す設定です。1 回のリクエストがサーバーのメモリを使い切る危険を抱えるため、更新したら元に戻すことを前提にしてください。アドバイザリは、この設定を入れたあと、プールやディレクトリ、アプリケーションの設定が有限の上限値に戻していないかを確かめるよう勧めています。
要点
どの設定を組み合わせても、アドバイザリの結論は「更新が唯一の確実な対策」です。暫定策を入れるときは、更新の期日も一緒に決めてください。
8.1 以前と 8.2 の期限
通常の修正版リリースは、8.2 から 8.5 の 4 系統です。公式告知には、サポート終了済みの 7.4・8.0・8.1 向けに最小限のソース修正を提供したことも追記されています。ソースからビルドする人や LTS ベンダーを利用できない人向けの対応であり、継続的な公式サポートの代わりにはなりません。
PHP 8.2 を使っている場合も、安心はできません。8.2.35 のリリース告知は、8.2 が 2026 年 12 月 31 日に EOL を迎えると書いています。それ以降は、PHP プロジェクトの公式サポートの外になります。更新と並行して、8.3 以降へ移行する計画を立てることを勧めます。
古い PHP のまま動かしている場合は、PHP を上げるとアプリケーションが動かなくなることが、更新を止めている理由かもしれません。その場合は、設定の工夫を重ねる前に、システムの作り替えを含めて計画を立てる段階です。EOL を迎えたシステムの進め方は EOL を迎えたシステムの移行 で整理しています。
更新したあとにやること
更新して終わりにせず、次の 4 点を確認します。
- 暫定策で変えた設定を戻すか決める。
memory_limit=-1のような上限を外した設定は、更新後に元へ戻します - ワーカーを再起動する。アドバイザリは、設定を変えたあとにすべてのワーカーを再起動するよう書いています
session.upload_progress.enabled=0を残すか判断する。アドバイザリは、この機能を使っていないなら、更新後も無効にしておくことを勧めています- ログと権限を見直す。Web サーバーの実行ユーザーが持つ権限、クラウドの IAM ロール、ログの保存期間を確かめます
アドバイザリは、ログの記録を整えても侵害がなかった証明にはならないとも書いています。更新の前に不審なリクエストが届いていないかは、アクセスログとエラーログで見てください。
暫定策で止めてよいのか
FIXIT設定を変えれば、更新は後回しにしていいの?
Dodaiいいえ。公式が、設定だけでは安全にならないと書いています。更新までの時間稼ぎに限ります。
FIXITじゃあ、更新できない事情があるときは?
Dodai暫定策を入れ、更新の期日を決めます。古い PHP が原因なら、アプリの改修も計画に入れます。
緊急更新に備えてサーバーの台帳を作る
FIXIT は AI 駆動開発のクリエイティブスタジオとして、プロダクト開発のクライアントワークで、依存するランタイムのバージョンと保守の期限を台帳で管理することを勧めています。今回のような緊急の更新で「どのサーバーでどの PHP が動いているか」を答えられないと、確認の着手が遅れます。
PHP のバージョンが古く、更新すると動かなくなるシステムは、暫定策だけでは脆弱性は解消しません。保守を担当していた開発会社と連絡が取れない場合を含め、現状の調査から相談できます。保守の引き継ぎは 開発会社の乗り換え・システム引き継ぎ、作り替えは システム刷新・リプレイス をご覧ください。
まとめ
php2shell への対応は、修正版への更新が中心です。Web を処理している PHP を特定し、パッケージの changelog でバックポートの有無を確かめます。未修正なら、PHP 8.5.12・8.4.27・8.3.36・8.2.35 または修正を取り込んだパッケージへ更新してください。更新までの暫定策は時間稼ぎにとどめ、更新の期日を決めてください。
8.1 以前を使っている組織と、2026 年 12 月 31 日に EOL を迎える 8.2 を使っている組織は、今回の更新と並行して移行の計画を立てる必要があります。情報の更新は、php.net の告知 と 2 件のアドバイザリで確かめてください。古い PHP のシステムの引き継ぎや作り替えを検討している場合は、お問い合わせ からご相談ください。



