本日1件のお問い合わせがありました。

✉️FIELDにお問い合わせ

システム開発アプリケーション開発

PHP2Shell 修正パッチを読み解く|CVE-2026-109618 / 109619 で本当は何が壊れ、何が直ったのか(WordPress運用者向け)

10月21日の記事「PHP緊急脆弱性「php2shell」深掘り調査」は、修正版が公開される前に書いたものでした。そのため、技術的な中身は「有力な推測」までしか書けませんでした。

その後、PHP 公式は修正版とあわせてセキュリティアドバイザリ(GHSA)を公開し、修正コミットのソースコードも読めるようになりました。この記事では、PHP 公式のアドバイザリと修正コミットそのものを読んで、本当は何が壊れていて何が直されたのかを整理します。そのうえで、WordPress を運用している方は何を確認すればよいのかをまとめます。

  • 確認日:2026年10月25日(日本時間)
  • 主に確認した一次情報:PHP 公式のアドバイザリ(GHSA-w8hw-w9fx-j79w / GHSA-6wmf-4rv5-p3rp)、php.net のお知らせ、修正コミット 3584a98(php-src)、AWS セキュリティ速報 2026-143、さくらインターネットとエックスサーバーの公式告知、W3Techs

参照先の URL は記事末尾にまとめています。


結論

今回の「PHP2Shell」は、PHP や WordPress の入力チェックを一つ追加して塞ぐような脆弱性ではありません。修正は PHP ランタイムそのものの、

  • メモリ不足(OOM)のときの異常終了のしかた
  • HTTP リクエストをまたいで残る内部状態の初期化タイミング

を大きく作り直すものです。PHP 公式は次の2件を、認証なしのリモートコード実行(RCE)につながる Critical(CVSS v4.0 9.2)としています。

CVEPHP 公式の名称一言でいうと
CVE-2026-109618RCE via OOM corruptionメモリ不足で処理が中断され、作りかけのデータを後始末が正常なデータとして扱ってしまう
CVE-2026-109619RCE via stale global state解放済みメモリを指す内部状態が残り、同じワーカーの次のリクエストがそれを使ってしまう

修正版は次の4つです。

  • PHP 8.5.12
  • PHP 8.4.27
  • PHP 8.3.36
  • PHP 8.2.35

特に大切なのは、WordPress に脆弱性があるわけではないという点です。攻撃の対象は、その下で HTTP リクエストを処理している PHP 本体です。PHP 公式は Apache mod_php について、アプリケーションのコードが動き出す前に、認証なしの HTTP リクエストだけで RCE に到達できることを実証済みとしています。そのため「WordPress をメンテナンスモードにする」「ログインを禁止する」といったアプリケーション側の対処では防げません。

攻撃も仮定の話ではありません。Amazon の脅威インテリジェンスチームは、自社のハニーポット「MadPot」で、一般公開の4日前にあたる 10月17日に PHP2Shell を狙った攻撃試行を観測したと報告しています。公開当日にも、修正版が出る約12時間前の 02:00 UTC ごろから、複数の PoC(攻撃コード)による試行が観測されました。それらが実際のシステムに対して成功したかどうかはわかっていませんが、Amazon は、少なくとも10月17日までさかのぼって不審な動きを調べるよう勧めています。

一方で、ネット上でよく見かける次のような説明は、厳密には言い過ぎです。

  • 「AWS を使っているなら危ない」
  • 「安全なのはこの4バージョンだけ」
  • 「更新以外の対応方法は存在しない」

完全な修正は PHP の更新だけですが、効果が限定的な暫定策は公式に示されています。また、Linux ディストリビューションやレンタルサーバー会社が修正をバックポートした環境では、表に出ている PHP のバージョン番号だけでは安全かどうかを判断できません。

修正パッチは実際に何を直しているのか

修正の本体は、php-src のコミット 3584a98「Avoid state corruption via bailout」です。コミットメッセージには、修正内容が2行で書かれています。

- Replace bailout on OOM with UnwindExit
- Properly reset various globals that may be accessed during startup

Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)

一つのコミットで2件の CVE を同時に直しています。変更されたファイルは389個(テストを除いても112個)あり、Zend Engine だけでなく、session、standard、json、mbstring、gd、soap、opcache など多くの拡張に及んでいます。どこか一箇所に if 文を足した修正ではありません。

修正は大きく次の2本柱です。

  1. OOM のときに、危険な場所から「瞬間移動」で抜け出さないようにする
  2. 次のリクエストが始まる前に、内部状態を確実にリセットする

1. メモリ不足時の終了方法を根本から変えた

一つ目は、PHP がメモリ不足(OOM: Out Of Memory)になったときの処理です。修正前の流れを概念的に書くと、次のようになります。

HTTPリクエストを解析
        ↓
PHP内部のデータ構造を書き換え始める
        ↓
途中でメモリ確保に失敗
        ↓
zend_bailout()
        ↓
longjmp() で処理の途中から一気に脱出
        ↓
本来その途中で行うはずだった後始末が飛ばされる
        ↓
shutdown処理が「完成したデータ」だと思って不完全な状態を触る
        ↓
メモリ破壊

PHP 公式のアドバイザリも、旧実装が OOM 時に longjmp() でスタックを巻き戻していたこと、リクエストのメモリが「完全に初期化される前に一時的に到達可能な状態」になる箇所があり、そこで確保に失敗すると shutdown 処理がその無効なメモリを読んだり、それをもとに分岐したりしてしまうことを根本原因として説明しています。しかも、失敗した確保と、後で誤用されるデータが同じとは限らないとも書かれています。

修正版では、メモリ上限を超えたときにすぐ longjmp() するのをやめました。新しい流れは次のとおりです。

旧PHP
  OOM
   ↓
  longjmp
   ↓
  後片付けを飛び越えて脱出

修正版
  OOM
   ↓
  「OOMが起きた」と記録(保留)
   ↓
  VM interrupt を立てる
   ↓
  VMの安全な地点まで進む
   ↓
  UnwindExit(例外の仕組みで終了)
   ↓
  順番にスタックを巻き戻して終了

ソースでは zend_handle_delayed_oom() という関数が追加され、保留された OOM を安全な地点で拾って zend_throw_unwind_exit() を呼び、通常のスタック解放の経路で終了する構造になっています。PHP 公式はこれを、次の VM safe point で発生する「graceful soft OOM」と呼んでいます。

さらに、第二段階の hard OOM も追加されています。soft OOM を記録した後もメモリ消費が止まらず、二つ目の上限に達した場合は、壊れかけた処理を続けず、_exit(137) でワーカープロセスごと終了します。「多少可用性を犠牲にしても、壊れた内部状態のまま攻撃者に制御を渡すよりはワーカーを止める」という設計です。

この二つ目の上限には、新しい INI 設定 memory_hard_limit_percent が用意されています。既定では memory_limit の 2倍、memory_limit が 1GB を超える場合は memory_limit+1GB になるようソースに実装されています。

あわせて、メモリ確保の失敗時に即座に bailout するのではなく、失敗を呼び出し側に返して処理できる fallible な確保への書き換えが、パッチ全体で広く行われています。

2. 次のリクエストに残っていたポインタを早めに消す

二つ目は、さらに PHP ランタイムらしい問題です。

PHP-FPM や Apache mod_php は、リクエストごとに PHP プロセスを起動しては終了しているわけではありません。同じワーカーが何件ものリクエストを順番に処理します。そのため PHP の内部には、ワーカーが生きている間ずっと存在する global state があります。問題は、それが「前のリクエストの間だけ有効だったメモリ」を指したまま残ることがある点でした。

正常であれば、次のように進みます。

Request A
   ↓
request用メモリを使う
   ↓
global stateをリセット
   ↓
request用メモリを解放
   ↓
Request B
   ↓
新しい状態で処理

しかし、途中で処理が打ち切られたりして順番が崩れると、こうなります。

Request A
   ↓
global pointer ───→ Request Aのメモリ
                         ↓
                    メモリ解放
                         ×
global pointer ───→ 解放済み領域

Request B
   ↓
通常の初期化(RINIT)より前に、そのpointerを使う
   ↓
Use-After-Free

これが CVE-2026-109619 の中心です。公式アドバイザリによると、「リクエストのメモリを解放する前にリセットされるべき状態」(error・session・object・extension の状態)が、ワーカーの global から参照できたまま残ります。そうなる原因は二つです。

  • 致命的な中断:構文エラーやコンパイルエラー、捕捉されない例外、require の失敗、実行時間切れ、そして OOM などで処理が打ち切られ、対になるリセット処理が実行されない
  • shutdown 中の警告:後半の shutdown 処理で拡張やサーバーが出した警告などが、一度クリアしたエラー状態をもう一度埋めてしまう

そして、残った古い状態を次のリクエストの初期化前に使ってしまう処理として、公式は次の二つを挙げています。

  • INI 適用時の警告:リクエスト開始時の INI 適用で警告・注意・非推奨メッセージが出ると、古いエラー状態を使ってしまう。画面に出すかログに残すかは関係ない。Apache mod_php の .htaccess や php_value が確認済みの経路
  • セッションのアップロード進捗(Session Upload Progress):前のリクエストが残したセッションやデコーダーの状態を、通常の初期化の前に使ってしまう

確認済みのケースとしてもっとも強いのは、PHP 8.5 の新機能 fatal_error_backtraces まわりのエラー状態で、mod_php での RCE の実証はこれをもとにしています。セッションのアップロード進捗の経路は、mod_php と FPM の両方で検証されています。公式は「Session upload progress は既定で有効であり、アプリケーションが session_start() を呼ばなくても関係する」と注意しています。

修正では、PHP 本体に php_basic_early_rinit() という、通常の RINIT よりさらに前に実行する初期化が追加されました。php_request_startup() の中で、リクエストのデータを処理するより前に呼ばれます。

php_request_startup()
    ↓
zend_activate()
    ↓
php_basic_early_rinit()   ← 追加
    serialize_lock = 0
    serialize state = clear
    unserialize state = clear
    URL scanner state = reset
    ↓
sapi_activate()
    ↓
HTTP body / session upload progress などの処理
    ↓
通常のRINIT

ソースのコメントには「セッションのアップロード進捗の処理は、RINIT より前に、セッションを(アン)シリアライズし、セッション ID を URL リライターに登録する」と理由が書かれています。

これは考え方の大きな変化です。「前のリクエストが正常に終わったはずだ」と信頼するのではなく、次のリクエストを受ける側でも、危険な状態を使う前に明示的に消す設計になりました。

セッションのアップロード進捗はさらに守りが固められた

session.upload_progress は、ファイルアップロードの進捗をセッションに書き込む機能です。厄介なのは、PHP のスクリプトが動き出す前、つまり RINIT より前に動くことです。

修正版では、この処理中であることを示す内部フラグ in_rfc1867_update が追加されました。さらに、この間にセッションを unserialize するときは、オブジェクトを本来のクラスとして復元せず、すべて __PHP_Incomplete_Class として扱うよう強制しています。ソースのコメントにはこう書かれています。

RINIT より前で、ユーザーコードが動いてはいけない段階なので、オブジェクトは __PHP_Incomplete_Class のまま扱う。オートロードも、unserialize_callback_func も、__wakeup() や __unserialize() も呼ばず、内容は変更せずに書き戻す。(ソースコメントを筆者が要約・翻訳)

HTTP multipart upload
       ↓
session upload progress
       ↓
セッションをunserialize
       ↓
旧: 通常のPHPオブジェクトとして復元できる
    → マジックメソッド等に入り得る
新: incomplete class のみ
    → ユーザーコードを一切呼ばせない

ここまで見ると、今回のパッチが「怪しい HTTP パラメータ名をブロックした」ような修正ではないことがよくわかります。PHP のリクエストのライフサイクルそのものを修理しているのです。

サーバーに実際に入るもの

WordPress のディレクトリに「PHP2Shell対策.php」のようなファイルが追加されるわけではありません。置き換わるのは PHP の実行ファイルそのものです。

旧 php-fpm / php / libphp
      ↓
パッケージ更新(またはソースから再ビルド)
      ↓
修正入りの php-fpm / php / libphp
      ↓
ワーカーを再起動して初めて反映

Apache mod_php なら PHP の Apache モジュール、PHP-FPM なら FPM、CLI なら PHP CLI のバイナリが対象です。WordPress のファイルを更新しても修正は入りません。逆に、レンタルサーバー側が PHP に修正を入れていれば、利用者が WordPress に何かをする必要はありません。

未修正だと何ができてしまうのか

ここでは攻撃コードではなく、攻撃者がどういう段階を経て任意のコード実行に到達するのかを、公式アドバイザリの範囲で説明します。

メモリ不足を利用する攻撃(CVE-2026-109618)

ポイントは、攻撃者が意図したタイミングで OOM を起こせることです。公式アドバイザリは、見かけ上は制限内に収まったまま memory_limit に到達させられる、multipart(ファイルアップロード形式)の解析の弱点を三つ挙げています。

  • 使える Content-Length がない multipart リクエストは、最初の post_max_size のチェックをすり抜けられる
  • 各パートに付けられるヘッダーの数に上限がなく、メモリ上ではかなり膨らむ
  • 空のファイル欄は max_file_uploads に数えられないのに、ファイル情報の配列は作られる。入れ子の項目名にするとその処理が掛け算で増える

これを使った攻撃の流れは、おおむね次のとおりです。

Internet
   │  細工したHTTP POST(multipart)
   ▼
PHPのリクエスト解析
   │  制限をすり抜けてメモリを消費
   ▼
memory_limit に到達
   │  内部データを書き換えている途中でOOM
   ▼
旧PHPの longjmp / bailout
   │  後始末が飛ばされる
   ▼
不完全な内部状態
   ▼
request shutdown
   │  無効なポインタを正常値として処理
   ▼
メモリ破壊
   │  ヒープの配置を攻撃者が整える
   ▼
制御フローの乗っ取り
   ▼
Webワーカーの権限で任意コード実行

公式は、既定の入力制限・メモリ制限のままの mod_php(prefork・複数ワーカー)に対して、認証なしの HTTP リクエストによる RCE を実証したと書いています。理由は、mod_php が「リクエストの開始処理に失敗した場合でも、必ず終了処理を呼ぶ」ためで、リクエスト本体の自動解析の段階、つまりアプリケーションのコードが動く前に条件がそろってしまいます。

攻撃者 → Apache → PHPのリクエスト解析 → 攻撃成立 → (WordPressまで届かない)

実行環境(SAPI)ごとの評価は次のとおりです。

SAPI公式アドバイザリの評価
Apache mod_php実証済み。アプリケーションのコードより前に成立
PHP-FPMソース分析のみ。開始処理に失敗すると子プロセスが終了するため mod_php とは事情が違うが、通常の開始後の OOM では到達し得る。完全な攻撃は未実証
FrankenPHP終了処理を無条件に呼ぶため、影響を受ける可能性が高い(ソース分析)
LiteSpeed(LSAPI)FPM に近い。アプリケーション次第で攻撃できる可能性が高いが未検証

「FPM だから安全」という意味ではありません。FPM でも条件次第では到達し得るうえ、CVE-2026-109619 の経路は FPM でも検証されています。

古い状態を次のリクエストで使わせる攻撃(CVE-2026-109619)

こちらは二段階の攻撃です。

Request A
   ├─ 致命的エラー / OOM / 実行時間切れ 等で中断
   └─ 解放されるメモリへのポインタがglobalに残る
                      ↓
                 request終了・メモリ解放
                      ↓
            globalにはポインタが残ったまま

              同じPHPワーカー

Request B
   ├─ 通常の初期化より前の処理
   └─ INI適用時の警告 / session upload progress 等
                      ↓
             古いポインタを使用
                      ↓
                 Use-After-Free
                      ↓
                     RCE

この攻撃は、中断させるリクエストと、それを踏ませるリクエストが同じワーカーに入る必要があります。ただし公式は「ワーカーが複数あることや、ワーカーの入れ替えは1回あたりの成功率を下げるだけで、条件そのものはなくならない」と明言しています。

RCEを取られた後にできること

成立した後の権限は、原則として PHP を動かしている Web ワーカーのアカウントの権限です。いきなり root を取られる脆弱性ではありません。AWS も、影響は「該当するワーカーと、そのアプリケーションレベルの権限の範囲」と説明しています。

それでも WordPress にとっては十分に深刻です。攻撃者が得る能力をイメージで表すと、次のような状態です。

# 誰の権限で動いているか
id

# WordPressの設定ファイルを読む
cat /var/www/***/wp-config.php

# 書き込み可能な領域のファイルを変更
[ファイル作成・変更コマンド]

# そのサーバーから到達できるDBや内部サービスへ接続
[接続コマンド]

wp-config.php には通常、データベース名・ユーザー名・パスワード・ホストなどの接続情報が書かれています。PHP ワーカーがこのファイルを読める構成なら、RCE の後に DB の資格情報を盗まれ、データベースにアクセスされる可能性があります。PHP2Shell が直接 DB の権限を与えるわけではなく、RCE によって既存の資格情報に手が届くことで起きる二次被害です。

環境の権限設定によっては、

  • 記事やユーザー情報の窃取・改ざん
  • WordPress のファイルの改ざん
  • 秘密情報・API キーの取得
  • バックドアの設置
  • 外部への通信、他システムへの横展開の足がかり

につながり得ます。一方で、PHP ワーカーが読めないファイル、ネットワーク的に届かないサービス、root 専用の操作まで、この脆弱性だけで自動的にできるようになるわけではありません。

そもそも、なぜうちが攻撃されるのか

「うちの会社が誰かに狙われているのか」と思われるかもしれませんが、多くの場合、まず心配すべきなのは標的型の攻撃ではありません。

インターネットには、脆弱なサーバーを自動で片っ端から探している bot や攻撃ツールがあります。Amazon は、公開当日に観測された攻撃試行について、単一のグループではなく複数の攻撃者が関わっているとみています。

感覚としては、ドラクエの勇者が民家のツボを片っ端から割っていくようなものです。「あなたの家だから」ではなく、「割れるツボがそこにあるから割る。何か入っていたらラッキー」。そのくらいのイメージが近いです。

小規模なサイトでも、「うちは有名じゃないから大丈夫」とは考えない方がよいでしょう。

自分のPHP・WordPressをどう判定するか

PHP公式の修正版とサポート状況

系列PHP2Shell の修正PHP 公式のサポート
PHP 8.58.5.12 以上サポート中
PHP 8.48.4.27 以上サポート中
PHP 8.38.3.36 以上サポート中
PHP 8.28.2.35 以上2026年12月31日で EOL
PHP 8.1 / 8.0 / 7.4リリースなし。ソースへの最小限のバックポートのみEOL
PHP 7.3 以前公式の対応なしEOL

PHP 8.2 は 8.2.35 で修正されますが、php.net は「8.2 は2026年12月31日で EOL を迎え、それ以降はセキュリティ修正も出ない」と案内しています。今から環境を変えるのであれば、8.3 以上を視野に入れるのが合理的です。

7.4・8.0・8.1 について、PHP Security Team は今回の重大性から、ソースからビルドする人向けの最小限のバックポートを例外的に用意しました。実際のコミットにも「Minimal mitigation for EOL version」と書かれています。これは修正版のリリースではなく、自分でビルドするためのソースです。なお、AWS のセキュリティ速報は「EOL 系列では CVE-2026-109618 の修正はない」としています。AWS が提供するパッケージの扱いとして読むべきですが、いずれにしても EOL 系列は「今回はなんとかふさげる場合がある」程度と考えてください。今後の脆弱性は直してもらえないため、7.4 以下を長く使い続ける理由にはなりません。

バージョン番号だけで判断してはいけない

ここがもっとも誤解されやすいポイントです。

php.net は「8.1 以前は PHP プロジェクトからの更新はないが、ディストリビューションや LTS ベンダーがバックポートを提供している場合がある」と案内しています。ベンダーが修正だけを古い系列に取り込むと、表示されるバージョン番号は古いまま、中身は修正済みということが起きます。逆に、バージョン番号は新しく見えても、ワーカーを再起動していなければ古いコードが動き続けています。

判断の基準は次のとおりです。

自分で upstream の PHP を入れている
    → 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 以上か

OSパッケージの PHP
    → OSベンダーのセキュリティ情報とパッケージのリビジョン

レンタルサーバー
    → レンタルサーバー会社の対応発表

Docker
    → 修正済みのイメージで rebuild / redeploy したか

AWSの場合

「AWS を使っている=危ない」という言い方は正確ではありません。AWS のセキュリティ速報(2026-143)は、AWS のサービス自体は影響を受けないと明記しています。そのうえで、利用者が PHP を動かしているサービスについては次のように案内しています。

  • Elastic Beanstalk:PHP 8.2〜8.5 の修正版プラットフォームを提供。マネージドプラットフォーム更新を有効にしていれば、次のメンテナンスウィンドウで自動適用
  • Amazon Linux:修正版の PHP パッケージを提供済み。詳細は Amazon Linux Security Center
  • Lightsail:新しいブループリントを提供。ただし稼働中のインスタンスを AWS 側でその場で更新することはできないため、新しいインスタンスを作って移行する必要がある
  • EOL 系列(PHP 5.4〜8.1):修正なし。CVE-2026-109619 向けの暫定設定を入れ、すぐにサポート中の系列への移行を始めること

つまり、EC2・VPS・自己管理の Docker など、OS や PHP を自分で管理している環境は、自分で確認・更新が必要です。

さくらインターネットの場合

さくらのレンタルサーバは、公式告知(10月22日公開・23日追記)で、コントロールパネルから選べるすべての PHP バージョン(5.2〜8.3)に必要な修正を適用済みで、利用者が行う緊急の対応はないとしています。そのうえで、サポート中の PHP への移行を勧めています。

ただし「さくらのVPS」や「さくらのクラウド」で利用者が自分で PHP を動かしている場合は、その PHP を利用者自身で更新する必要があります。

エックスサーバーの場合

エックスサーバーの公式告知には、次の対応経過が載っています。

日時内容
10月22日 01:10PHP 8.2〜8.5 への修正適用を開始
10月22日 06:45PHP 8.2〜8.5 の対象サーバーすべてに適用完了
10月22日 12:00PHP 7.4〜8.1 の対象サーバーすべてに適用完了
10月22日 14:00PHP 5.6〜7.3 の対象サーバーすべてに適用完了
10月23日 17:00PHP 5.1〜5.5 の対象サーバーの過半数に適用完了

共用サーバー(エックスサーバー、エックスサーバービジネス、XServer for WordPress)で PHP 5.6〜8.5 を使っている場合は、「今回の脆弱性への対策として、急いで PHP バージョンを変更する必要はない」とされています。ただし「利用状況によっては追加の対策をお願いする場合がある」とも書かれているので、管理画面のお知らせは引き続き確認してください。VPS は利用者が OS と PHP を管理しているため、同社は PHP に修正を適用していません。自分で更新が必要です。

自前サーバーでの確認方法

まず SSH で次を確認します。

php -v

ただし、これは CLI 版の PHP です。Web 側は別の PHP-FPM や別のバージョンで動いていることがよくあります。CLI が 8.4.27 でも Web 側は古いまま、ということがあり得ます。(実際、当社が管理しているサーバーにも「CLI は古いまま、Web 側だけ修正版に切り替えた」構成があります。)FPM の実際のプロセスも確認してください。

ps aux | grep '[p]hp-fpm'

パッケージの情報もあわせて確認します。

# Debian / Ubuntu系
dpkg -l | grep -E 'php.*(fpm|cli|apache)'

# RHEL / Amazon Linux系
rpm -qa | grep '^php'

Web 側の PHP そのものを確かめたい場合は、次のような確認用ファイルを一時的に置き、確認したらすぐに削除します。

<?php
echo PHP_VERSION, ' ', PHP_SAPI;

最後に、更新した後に PHP-FPM や Apache を再起動したかも確認してください。再起動するまでは、古いワーカーが古いコードのまま動き続けます。

未修正だった場合の緊急対応

自分で管理しているサーバーで修正が入っていないとわかった場合は、インターネットから到達できる状態のまま作業しない方が安全です。

WordPressのメンテナンスモードでは防げない

mod_php では、WordPress に処理が渡る前に攻撃が成立します。

WordPressメンテナンスモード
            ↓
      PHPはまだHTTPを処理する
            ↓
        防御にならない

止めるなら、PHP より手前の層で止めます。

  • ロードバランサーのターゲットから外す
  • リバースプロキシで PHP への到達を止める
  • Web サーバー/PHP ワーカーを停止する
  • ネットワークレベルでアクセスを遮断する

そのうえで PHP を修正版に更新し、関係するワーカーをすべて再起動してください。Amazon は10月17日の時点で攻撃試行を観測しているので、ログやファイルの改ざん有無はその日までさかのぼって確認するのが安全です。

公式の暫定策(どれも完全ではない)

PHP 公式は、すぐに更新できない場合の暫定策を示しています。ただし、どれも「完全な対策ではない」と明記されています。

CVE-2026-109619 向け

session.upload_progress.enabled = 0

確認済みのセッション経路を止められます。設定後は全ワーカーを再起動します。公式は、この機能を使っていないならパッチ適用後も無効のままにしておくことを勧めています。WordPress 本体は PHP のセッションを使わないため、多くのサイトでは無効にしても影響はほとんどありません(プラグインでアップロード進捗を表示している場合は確認してください)。

PHP 8.5 では、fatal_error_backtraces=0 で確認済みの RCE の原因を一つ消せます。ただし、ほかの経路には効きません。ワーカーを1リクエストごとに入れ替える pm.max_requests=1 も、性能が許すなら選択肢として挙げられています。

CVE-2026-109618 向け

  • 管理者レベルで memory_limit=-1 を強制する:攻撃が頼りにしている「予測できる上限」をなくす。ただし mmap() が失敗すれば longjmp() の経路は残るので不完全。プールやディレクトリ、アプリ側の設定で上限が戻っていないかも確認する
  • post_max_size を控えめにし、フロント側(Web サーバーやリバースプロキシ)でリクエストサイズ、パート数、パートごとのヘッダー数、アップロード数を制限する
  • multipart を使わないサービスなら、フロント側で multipart 自体を拒否する
  • RLIMIT_AS や RLIMIT_DATA での制限は避ける(mmap() の失敗を起こし、かえって脆弱な経路を通るため)

まとめると、暫定的に攻撃経路を狭める方法はいくつかありますが、二つの脆弱性をまとめて確実に解消する方法は修正版 PHP への更新だけです。

10月23日の追加告知:session.upload_progress は当面オフに

PHP 公式は10月23日、追加のお知らせを出しました。修正版でも残っている、別の RCE の経路(CVE-2026-115560)についてです。

公式によると、この問題は「設定ファイルで session.serialize_handler を php_binary か php_serialize にしたうえで、実行時に ini_set() で php に切り替えてから session_start() を呼ぶ」という珍しい組み合わせで、かつアップロード進捗が有効な場合にだけ起きます。実際にはまず起きない構成のため、次の通常リリースで修正し、詳細もそのときに公開するとしています。

そのうえで公式は、次の通常リリースまでは session.upload_progress.enabled=0 にしておくことを勧めています。10月21日の時点でこの設定を入れていれば、そのままで追加の作業は不要です。実行時にシリアライズハンドラを切り替えないアプリケーションであれば、有効のままでも問題ないとされています。

PHPやWordPressは危ないから、使わない方がいい?

今回の件だけを理由に「PHP や WordPress は危険だからやめた方がいい」と考える必要はないと思います。

W3Techs の統計(2026年10月24日時点)では、PHP はサーバーサイド言語がわかる Web サイトの 69.3%、WordPress は全 Web サイトの 39.6% で使われています(CMS の中でのシェアは58.3%)。よく「PHP は全サービスの7割」と言われますが、正確には「サーバーサイド言語が判明している Web サイトの約7割」です。

利用者が多い技術には両面があります。

  • 攻撃者から見ると:一度攻撃ツールを作れば大量のサイトに使い回せるので、狙う価値が高い
  • 防御側から見ると:利用者・技術者・ホスティング会社・セキュリティ会社が多く、脆弱性情報、修正版、検知方法、回避策が非常に速く共有される

今回も、PHP 公式、Linux ベンダー、AWS、国内のレンタルサーバー各社が、公開から1日ほどで対応を進めました。一件の CVE だけで「PHP は危険」とも「PHP は安全」とも言い切れません。言えるのは、広く使われているランタイムでは一件の脆弱性の影響が大きくなる一方、対応も速く広がる、ということです。

Node.js や Python に乗り換えれば、PHP2Shell そのものからは離れられます。しかし、ランタイム、フレームワーク、パッケージ、OS、リバースプロキシを更新し続ける責任はなくなりません。言語を変えるより先に、次の点を見直す方が本質的です。

  • 誰がランタイムを更新するのかが決まっているか
  • EOL のバージョンを残さない仕組みになっているか
  • 緊急パッチを数時間単位で適用できる体制・構成になっているか
  • 問題が起きたときに、すぐ切り離して更新できる構成になっているか

まとめ

  • PHP2Shell は WordPress ではなく PHP 本体の脆弱性。mod_php では WordPress が動く前に攻撃が成立する
  • 修正(コミット 3584a98)の中身は、「OOM 時の longjmp() をやめて安全に終了する(soft OOM/hard OOM)」と「リクエスト間に残る状態を早めに初期化する(php_basic_early_rinit())」。リクエストのライフサイクルそのものの修理
  • 修正版は 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35。OS パッケージやレンタルサーバーではバックポートがあるため、番号だけで判断しない。更新後のワーカー再起動も忘れずに
  • EC2・VPS・自己管理 Docker は自分で確認・更新。さくら・エックスサーバーの共用サーバーは事業者側で適用済み(VPS は自分で)
  • 未修正なら、メンテナンスモードではなく PHP より手前で遮断してから更新する。ログは10月17日までさかのぼって確認する
  • session.upload_progress.enabled=0 は、追加告知(CVE-2026-115560)も踏まえ、使っていなければ当面オフにしておく
  • 7.4 以下や 8.2 を使っているなら、今回の件とは別にサポート中の PHP への移行を計画する

今回のように、広く使われている基盤ソフトウェアで重大な脆弱性が見つかり、世界中で一斉に対応が必要になる事態は、頻繁に起きるものではありません。ただ、「一度安全にしたら終わり」ではありません。Web サービスを運用する以上、こうした緊急アップデートにすぐ対応できる体制を作っておくこと自体がセキュリティになります。

これを機に、PHP のバージョン、WordPress 本体・プラグイン、OS、バックアップ、アクセス制御、監視、サーバーの権限分離などを一度見直しておくことをおすすめします。

参照した情報源

  • php.net「Security advisory: Critical remote code execution vulnerabilities, update now」(2026年10月21日)/「Informational advisory: Session upload progress」(2026年10月23日) https://www.php.net/archive/2026.php
  • PHP 公式アドバイザリ CVE-2026-109618(GHSA-w8hw-w9fx-j79w) https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
  • PHP 公式アドバイザリ CVE-2026-109619(GHSA-6wmf-4rv5-p3rp) https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
  • 修正コミット「Avoid state corruption via bailout」 https://github.com/php/php-src/commit/3584a98bda0f2c0d367255b046798b0d3a221a19
  • AWS セキュリティ速報 2026-143「PHP web runtimes (CVE-2026-109618 and CVE-2026-109619)」 https://aws.amazon.com/security/security-bulletins/2026-143-aws/
  • Amazon Lightsail「Update PHP on Lightsail instances to address CVE-2026-109618 and CVE-2026-109619」 https://docs.aws.amazon.com/lightsail/latest/userguide/amazon-lightsail-update-php-security-vulnerabilities.html
  • The Register「Hackers pile on PHP2Shell as AWS reveals attacks began before disclosure」(Amazon MadPot の観測について) https://www.theregister.com/cyber-crime/2026/10/22/hackers-pile-on-php2shell-as-aws-reveals-attacks-began-before-disclosure/5304749
  • さくらインターネット「【重要】PHPの脆弱性に関する当社の対応状況について」 https://www.sakura.ad.jp/corporate/information/announcements/2026/10/22/1968226117/
  • エックスサーバー「予防的な安全対策に伴う公式サイト・管理画面等の一時停止のお知らせ」 https://www.xserver.ne.jp/news_detail.php?view_id=19734
  • W3Techs(サーバーサイド言語/WordPress の利用状況) https://w3techs.com/

Yamamoto Yuya

プロフェッショナルとしての高いスキルと知識を持ち、誠実さと責任感を大切にする。常に向上心を持ち、新たな挑戦にも積極的に取り組む努力家。