php2shell(CVE-2026-109618/CVE-2026-109619)とは?PHPの重大脆弱性の技術詳細と緊急対応手順

約24分で読めます by ぽんたぬき
php2shell(CVE-2026-109618/CVE-2026-109619)とは?PHPの重大脆弱性の技術詳細と緊急対応手順

php2shell(CVE-2026-109618/CVE-2026-109619)とは?PHPの重大脆弱性の技術詳細と緊急対応手順

最終更新日:2026年10月21日


3行サマリー(結論) ① Webリクエストを処理するすべてのPHP環境(mod_php・PHP-FPM・php-cgi等)が対象です ② php.ini変更やWAFのみでは完全回避はできません ③ 修正版(8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 以降)への更新が唯一の恒久対策です


2026年10月21日、PHPに認証不要で任意コード実行(RCE)が可能な脆弱性2件が公開されました。通称「php2shell」と呼ばれるこの脆弱性のCVSS v4.0スコアは9.2(Critical)。GMO Flatt Securityによる技術詳細の公開を受け、業界全体で緊急対応が広がっています。本記事では脆弱性の技術的な原因、影響を受けるバージョン、パッチ適用とロールバック手順、WAFによる一時緩和策までを運用者視点で整理します。


まず結論:いま何をすべきか(3分で読む対応チェックリスト)

1分でわかる危険度と優先度

今回の脆弱性は、次の3点において特に深刻です。

  • 認証不要・事前条件ほぼなしでWebサーバ権限のコード実行が成立する
  • Webshell設置 → 横展開 → データ窃取まで一直線のリスクがある
  • アプリケーションコードの実行前に攻撃が完結するため、フレームワークや認証機構による防御が効かない

「計画外メンテナンスを実施してでも即時適用」が求められるレベルです。

今日やることチェックリスト

  • php -v で全ホストのバージョンを棚卸しする
  • 修正版の有無をディストリのパッケージ情報で確認する
  • 緩和策(php.ini / WAF)を先行適用する
  • パッチ適用 → 動作確認 → ロールバック手順を準備する
  • アクセスログを遡り調査し、侵害の有無を確認する

php2shellの概要:何が起きたのか

公開の経緯とタイムライン

2026年10月21日、PHPプロジェクトは緊急パッチをリリースし、同日GMO Flatt Security(東京)が脆弱性の技術詳細を公開しました。Rapid7・Tenable・The Hacker Newsなど国際的なセキュリティメディアが一斉に報じ、はてなブックマークでは800件を超えるブックマークを集めるなど、業界全体に波紋が広がっています。

「php2shell」という通称の意味

「php2shell」とは、PHPリクエスト処理そのものを踏み台にシェルを取られる、という脅威モデルを端的に表した通称です。最大の特徴は、アプリケーション側の脆弱性ではなく、PHP処理系そのものの欠陥である点です。WordPressやLaravelなどのフレームワークのバージョンやコードの品質に関係なく、PHPが動いているだけで影響を受けます。

2つのCVEの関係性

CVE-2026-109618とCVE-2026-109619は、共通の根本原因として「Producer/Consumerモデルにおける不完全なリクエストデータのメモリ残留」を持ちます。攻撃トリガーが異なる2つの派生として理解するとわかりやすいでしょう。


CVE-2026-109618の技術詳細:OOM時のlongjmpによるRCE

脆弱性のメカニズム

CVE-2026-109618は、メモリ不足(OOM)エラー処理の過程で longjmp による大域脱出が発生し、リクエストデータが未初期化のままヒープ上に残留することで成立します。このヒープ状態の破壊を悪用することで、攻撃者は任意のコードを実行できます。

攻撃の流れ

  1. 攻撃者が細工した multipart/form-data リクエストを送信し、PHPプロセスのメモリを意図的に枯渇させる
  2. OOMエラーハンドリングが起動し、longjmp によって通常の処理フローが中断される
  3. 破壊されたヒープ状態を悪用して制御フローを奪い、任意コードを実行する

なぜ深刻なのか:「アプリコード実行前」に成立する

この脆弱性の最も恐ろしい点は、Webアプリケーションのコードが1行も実行される前に攻撃が完結することです。認証チェック・入力バリデーション・フレームワークのセキュリティ機構・IPアドレス制限など、アプリ層のあらゆる防御が機能しません。index.php の1行目に到達する前に、勝負は終わっています。


CVE-2026-109619の技術詳細:Stale Global StateによるUse-After-Free

脆弱性のメカニズム

CVE-2026-109619は、ワーカープロセスがリクエスト間で再利用される際に発生するUse-After-Free(UAF)です。前のリクエストで解放済みのメモリ領域を、後続のリクエストが参照してしまうことで、攻撃者がメモリ内容を制御できる状態になります。

3つの攻撃トリガー

この脆弱性は、以下の3つの状況が攻撃トリガーになります。

  1. fatal errorの発生:PHPが致命的エラーで処理を中断した際
  2. リクエストタイムアウト:設定されたmax_execution_timeを超過した際
  3. セッションアップロード進捗機能(PHP_SESSION_UPLOAD_PROGRESS):ファイルアップロードの進捗追跡機能を悪用した際

プロセス再利用アーキテクチャ特有のリスク

PHP-FPMやmod_phpのワーカー常駐モデルは、リクエストのたびにプロセスを起動・終了しないことでパフォーマンスを確保しています。しかしこのアーキテクチャ自体が攻撃面になります。pm.max_requests を設定してワーカーを定期的に再起動する構成はある程度の緩和にはなりますが、根本的な対策にはなりません。誤解のないよう注意が必要です。


CVSS v4.0スコア「9.2」の読み方

CVSSの深刻度レンジおさらい

スコア 深刻度
9.0〜10.0 Critical(緊急)
7.0〜8.9 High(重要)
4.0〜6.9 Medium(警告)
0.1〜3.9 Low(注意)

CVSS v4.0はv3.1と何が違うのか

CVSS v4.0は、v3.1と深刻度評語の閾値は共通ですが、環境評価指標・補足評価指標(Threat / Environmental / Supplemental)がより細分化されています。「自組織の文脈でスコアを再計算できる」のがv4.0の設計思想です。

たとえば今回のスコア9.2は「基本評価」ですが、自組織のWAFの整備状況・インターネット公開の有無・攻撃コードの公開状況(Threatメトリクス)を加味することで、実際の対応優先度をより精緻に判断できます。

9.2が実務上意味すること

  • 攻撃元:ネットワーク越し(インターネット経由で可能)
  • 必要権限:なし(認証不要)
  • ユーザー関与:不要(被害者の操作なしで成立)
  • 影響:機密性・完全性・可用性すべてに高影響

実務上の対応判断としては、定例メンテナンスを待たず即時適用が妥当です。社内システムの場合でも、内部犯リスクや多段的な侵害を考慮すれば対応を急ぐべきです。


影響を受けるPHPバージョンと環境

影響を受ける実行環境(SAPI)一覧

実行形態 リスク
Apache mod_php 最も高い
PHP-FPM 高い
php-cgi 高い
FrankenPHP 高い
LiteSpeed(lsphp) 高い
CLIのみ 相対的に低い

Webリクエストを処理するすべてのPHP環境が対象です。

修正済みバージョン一覧

ブランチ 修正版
PHP 8.2.x 8.2.35 以降
PHP 8.3.x 8.3.36 以降
PHP 8.4.x 8.4.27 以降
PHP 8.5.x 8.5.12 以降

PHP 8.1以下・7.xを使っている場合

PHP 8.1以下はセキュリティサポートが終了しています。ソースレベルのバックポートが提供される場合もありますが、公式な修正版バイナリのリリースは期待できません。RHELのELS(Extended Lifecycle Support)やUbuntu Proなどの商用拡張サポートを契約している場合は、ベンダーのアドバイザリを確認してください。中長期的には、サポート対象ブランチへの移行が唯一の正解です。

自分の環境を確認するコマンド集

# PHPバージョンとSAPIの確認
php -v
php -i | grep 'Server API'

# PHP-FPMの確認
php-fpm -v

# Apache mod_phpの確認
apachectl -M | grep php

# Dockerイメージのタグ確認(docker-compose.ymlなど)
grep -r "php:" docker-compose*.yml

# 複数ホストの一括棚卸し(Ansible)
ansible all -m shell -a "php -v" --become

パッチ適用手順:OS・環境別の実行コマンド

適用前にやること

  1. 現在のPHPバージョンとSAPI・拡張モジュール構成を記録する(php -v、php -m)
  2. 設定ファイルをバックアップする(/etc/php/ 以下)
  3. ステージング環境で先行検証する
  4. メンテナンスウィンドウ・告知・ロールバック判断基準を事前に合意する

Debian / Ubuntu(apt / ondrej PPA)

# パッケージリストの更新と適用
sudo apt update
sudo apt install --only-upgrade "php8.3-*"   # バージョン番号は自環境に合わせて変更

# PHP-FPMの再起動
sudo systemctl restart php8.3-fpm

# バージョン確認
php -v

RHEL系(dnf / yum / Remiリポジトリ)

# PHPとPHP-FPMの更新
sudo dnf update php php-fpm

# モジュールストリームを使用している場合
sudo dnf module update php:8.3

# 再起動
sudo systemctl restart php-fpm

# バージョン確認
php -v

Apache mod_phpの場合

# Apacheの再起動(gracefulでは不十分な場合があるため、通常のrestartを推奨)
sudo systemctl restart apache2   # Debian/Ubuntu
sudo systemctl restart httpd     # RHEL系

graceful や reload はワーカーの即時入れ替えを保証しないため、修正済みのPHPバイナリが確実に読み込まれるよう、完全な restart を実施してください。

Docker / コンテナ環境

# ベースイメージのタグを修正版に更新
FROM php:8.3.36-fpm-alpine   # 最新の修正版タグに変更
# 再ビルドとローリングデプロイ
docker build --no-cache -t myapp:latest .   # --no-cacheでイメージキャッシュを回避
kubectl rollout restart deployment/myapp    # Kubernetesの場合

注意:docker build のキャッシュにより「更新したつもり」で旧バージョンが動き続ける事故が多発します。必ず --no-cache フラグを使用し、docker exec で php -v を確認してください。

適用後の動作確認項目

# 修正版になっているか
php -v

# 拡張モジュールの読み込み確認
php -m

# OPcacheのクリア(必要な場合)
php -r "opcache_reset();"

# エラーログの確認
sudo tail -f /var/log/php*/error.log

その後、主要業務フローのスモークテスト(ログイン・決済・ファイルアップロード等)を実施します。


ロールバック方法:更新で不具合が出たとき

ロールバックを判断する基準

事前にしきい値を決めておくことが重要です。例えば「500エラー率が1%を超えたら即時ロールバック」「特定の拡張モジュールがロードできない場合はロールバック」など、チームで合意した基準を文書化しておきましょう。

Debian / Ubuntu でのダウングレード

# 旧バージョンへのダウングレード(バージョン番号は自環境に合わせて変更)
sudo apt install php8.3-fpm=8.3.35-1+ubuntu22.04.1+deb.sury.org+1

# 意図しない再更新を防ぐためのピン留め
sudo apt-mark hold php8.3-fpm php8.3-cli

# ピン留めの解除(再適用時)
sudo apt-mark unhold php8.3-fpm php8.3-cli

RHEL系でのダウングレード

# 直接ダウングレード
sudo dnf downgrade php php-fpm

# dnfトランザクション単位での巻き戻し
sudo dnf history list php     # 履歴を確認
sudo dnf history undo <ID>    # 対象IDの操作を巻き戻す

コンテナ環境でのロールバック

コンテナ環境では、直前のイメージタグへ再デプロイするのが最も安全かつ迅速です。

# Kubernetesでの即時ロールバック
kubectl rollout undo deployment/myapp

# docker-composeの場合
docker-compose up -d --no-build   # 旧タグに書き戻してから実行

ロールバック後に必須の対応

ロールバック後は脆弱な状態に戻っていることを前提に、後述のWAF・php.ini緩和策を即時適用してください。また、不具合の原因切り分けと再適用計画を立て、期限を設定して必ず修正版への移行を完了させることが重要です。


WAF・一時緩和策の設定例

大前提:設定変更では完全に防げない

GMO Flatt Securityも「設定変更による完全回避は不可能」と明言しています。以下の緩和策はあくまでもパッチ適用までの時間を稼ぐ暫定措置です。緩和策を適用したからといって対応が完了したわけではありません。

php.iniによる緩和

; CVE-2026-109619のトリガーの一つを封じる
; 副作用:アップロード進捗UIが機能しなくなる
session.upload_progress.enabled = 0

; OOMパスを踏ませない狙い(重要な注意事項あり・後述)
memory_limit = -1

; PHP 8.5のみ有効。デバッグ性が落ちる
fatal_error_backtraces = 0

⚠️ memory_limit = -1 の取り扱い注意:OOMパスを回避する目的の緩和策ですが、PHPプロセスがホストのメモリを際限なく消費し、ホスト全体がダウンするリスクがあります。この設定は必ずcgroupやコンテナのメモリ上限設定と併用することを前提条件にしてください。単独での適用は推奨しません。

設定変更後は、忘れずにPHP-FPMやApacheを再起動してください。

Cloudflare WAF

Cloudflareを使用している場合、カスタムルールで PHP_SESSION_UPLOAD_PROGRESS フィールド名を含む multipart/form-data のPOSTリクエストをブロックできます。

また、CloudflareはPHP2Shellの防御ルールをマネージドルールセットに既にデプロイしています。Cloudflareダッシュボードの「Security」→「WAF」→「Managed rules」でルールセットが有効になっているか確認し、最新の更新が適用されているかをチェックしてください。

ModSecurity(2.9.6以降)

# ARGS_POST_NAMES / FILES_NAMESのパース名長チェック
SecRule ARGS_POST_NAMES|FILES_NAMES "@gt 1024" \
    "id:9999001,phase:2,deny,status:400,msg:'Suspicious POST key length'"

# リクエストボディのパースエラーを拒否
SecRule REQBODY_ERROR "!@eq 0" \
    "id:9999002,phase:2,deny,status:400,msg:'Request body parse error'"

CRS(Core Rule Set)を使用している場合は、まず DetectionOnly モードで誤検知(false positive)の有無を確認してから Blocking モードに移行する段階的な導入を推奨します。

マネージドWAF・ホスティング事業者の対応状況

  • Imunify360:ルールセット8.83で公開済みエクスプロイトパターンをブロック済み
  • Akamai / Cloudflare:防御ルールを既にデプロイ済み
  • その他のマネージドWAFを使用している場合は、各社のセキュリティアドバイザリページでルールのバージョンを確認してください

緩和策の副作用まとめ

緩和策 効果 副作用
session.upload_progress 無効化 UAFトリガーを封じる アップロード進捗UIが停止
memory_limit = -1 OOMパスを回避 メモリ枯渇でホストがダウンするリスク
WAFルール 既知の攻撃パターンを遮断 誤検知の可能性・未知の亜種は通過

侵害されていないかを確認する

パッチ適用と並行して、既に攻撃を受けていないかのログ調査も必須です。

確認すべきログと痕跡

# アクセスログからPHP_SESSION_UPLOAD_PROGRESSを含むリクエストを検索
grep -i "PHP_SESSION_UPLOAD_PROGRESS" /var/log/nginx/access.log /var/log/apache2/access.log

# 異常なmultipartリクエストの確認
grep -i "multipart" /var/log/apache2/access.log | awk '{print $1, $7, $9}' | sort | uniq -c | sort -rn | head -20

# PHPエラーログでメモリ枯渇やセグフォルトを確認
grep -i "allowed memory size\|segfault\|child exited on signal" /var/log/php*/error.log

# PHP-FPMのクラッシュ確認
sudo journalctl -u php8.3-fpm --since "7 days ago" | grep -i "child\|signal\|crash"

Webshell・改ざんの探索

# Webルート配下の直近7日間に変更されたPHPファイル
find /var/www/html -name "*.php" -newer /var/www/html/index.php -mtime -7

# evalやbase64_decodeを含むファイルの検索
grep -r "eval\s*(\|base64_decode\s*(" /var/www/html --include="*.php" -l

# 想定外の実行可能ファイルの確認
find /var/www/html -executable -type f ! -name "*.sh"

# cronジョブ・SSH authorized_keysの確認
crontab -l; sudo crontab -l
cat ~/.ssh/authorized_keys

侵害が疑われる場合の初動

侵害の痕跡が見つかった場合は、次の順序で行動してください。

  1. 隔離:該当ホストのネットワークを切断する
  2. 証拠保全:ディスクスナップショットを取得し、ログを外部に保存する
  3. 認証情報の総入れ替え:SSH鍵・DBパスワード・APIキーすべてをローテーションする
  4. 再構築:単なるパッチ適用で侵害は消えません。Webshellが残存している可能性があるため、原則として再構築前提で対応する
  5. インシデント報告:必要に応じてCSIRT・外部専門家・監督官庁への連絡を行う

よくある質問(FAQ)

Q. CLIでしかPHPを使っていない場合は?

CLIはWebリクエストを受け付けないため、直接的な攻撃リスクは相対的に低いです。ただし、CI/CDパイプラインやcronで実行されるPHPスクリプトが、外部から注入された入力を処理する場合は注意が必要です。

Q. WAFを入れていればパッチは後回しでいい?

いいえ、推奨しません。 WAFは既知の攻撃パターンしかブロックできず、亜種や難読化されたペイロードは通過する可能性があります。WAFはあくまで時間稼ぎの手段です。修正版への更新を最優先にしてください。

Q. PHP 7.x / 8.1 を使い続けるしかない場合は?

まずWAFとphp.iniの緩和策を即時適用してください。並行して、サポート対象ブランチへの移行計画を経営層も含めた形で緊急策定することを強く推奨します。EOLバージョンの使用継続はこの脆弱性に限らず長期的なリスクです。

Q. レンタルサーバ・マネージドホスティングで自分では更新できない

プロバイダのアナウンスページやサポートチャネルを確認してください。主要なホスティング事業者の多くは既に対応済みか対応中です。対応状況が不明な場合は、サポートに問い合わせて対応予定を確認し、文書化しておきましょう。

Q. WordPress・Laravelなどのフレームワークは関係ある?

フレームワーク自体の脆弱性ではありません。PHPの処理系レイヤの問題なので、使用しているフレームワークに関係なく、PHPが動いている環境はすべて影響を受けます。

Q. 攻撃コード(PoC)は公開されている?

本記事執筆時点での詳細なPoCの公開状況はCVSSのThreatメトリクスを確認してください。脆弱性の性質上、PoCが公開されれば攻撃の敷居は一気に下がります。公開状況に関係なく、速やかなパッチ適用を強くお勧めします。

Q. 社内のみ公開のアプリも対応が必要?

必要です。内部犯・フィッシングによるVPN接続・別の侵害経路からの横展開など、「インターネットに公開していないから安全」とは言えません。優先度を下げることはできますが、対応を省略することは推奨しません。


まとめ:恒久対策はパッチ適用のみ

対応の優先順位(再掲)

  1. 緩和策の先行適用(数十分で可能):php.iniの変更とWAFルールの適用
  2. 修正版へのアップデート(唯一の恒久対策):8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 以降
  3. 侵害調査とログ保全:攻撃を受けていないかの確認
  4. EOLバージョンの移行計画:PHP 8.1以下を使用している場合はサポート対象バージョンへの移行

今回の教訓:処理系レイヤの脆弱性にどう備えるか

php2shellが示したのは、PHPそのものが攻撃対象になりえるという事実です。アプリケーションのコードをどれだけセキュアに書いても、処理系レイヤの脆弱性は防げません。この教訓を今後の運用改善に活かすために、以下の取り組みを検討してください。

  • バージョン棚卸しの自動化とSBOM:全ホスト・全コンテナのPHPバージョンを継続的に把握する仕組みを整備する
  • 無停止で更新できるデプロイ構成:Blue/Greenデプロイやローリングアップデートを整備し、緊急パッチを迅速に適用できる体制を作る
  • 脆弱性情報の受信経路の整備:PHP公式メーリングリスト・CISA KEV(Known Exploited Vulnerabilities)・主要ベンダーのアドバイザリRSSを購読し、情報が入ってくる仕組みを作る

処理系レイヤへの攻撃に対して、運用側が取れる手段はアップデートの迅速化と緩和策の準備だけです。今回の対応を通じて、緊急パッチ適用の一連のプロセスを整備する機会としてください。


参考リンク・一次情報


本記事の内容は2026年10月21日時点の情報に基づいています。脆弱性情報・パッチの提供状況は変化することがあります。最新情報は一次情報源をご確認ください。

関連記事

ESLint+PrettierからOxlint+Oxfmtへ — REALITYのモノレポでlintを9.3秒→2.95秒にした全手順

ESLint+PrettierからOxlint+Oxfmtへ — REALITYのモノレポでlintを9.3秒→2.95秒にした全手順

ESLint+PrettierからOxlint+Oxfmtへ — REALITYのモノレポでlintを9.3秒→2.95秒にした全手順 約460ファイルのモノレポでESLint+PrettierをOxlint+Oxfmtに置き換えた結果、lint実行時間が9.29秒→2.95秒(約68%削減)を達成しました。依存パッケージは14種から3種へ、設定ファイルも大幅にシンプルになっています。速度ベンチマ...

Aurora/RDS オンデマンドキャパシティ予約でDR・マイグレーションの「キャパシティ不足」を防ぐ

Aurora/RDS オンデマンドキャパシティ予約でDR・マイグレーションの「キャパシティ不足」を防ぐ

Aurora/RDS オンデマンドキャパシティ予約でDR・マイグレーションの「キャパシティ不足」を防ぐ Amazon Aurora・RDSを本番運用しているエンジニアであれば、一度は耳にしたことがあるのではないでしょうか。フェイルオーバーや復旧手順を実行した直後に表示される エラーの恐ろしさを。2026年10月、そのリスクを根本から断ち切る新機能「オンデマンドキャパシティ予約(On-Demand...

GitLab に CVSS 10.0 の緊急パッチ ― 正規表現コンパイラの整数オーバーフローとは何か、今すぐやるべきこと

GitLab に CVSS 10.0 の緊急パッチ ― 正規表現コンパイラの整数オーバーフローとは何か、今すぐやるべきこと

GitLab に CVSS 10.0 の緊急パッチ ― 正規表現コンパイラの整数オーバーフローとは何か、今すぐやるべきこと はじめに:2026年10月21日、GitLab が7バージョン同時リリース 2026年10月21日、GitLab は 19.5.1 / 19.4.3 / 19.3.6 / 19.2.9 / 19.1.9 / 19.0.10 / 18.11.13 の7バージョンを同時リリースし...

Mistral Large 4とは?1兆パラメータMoE × 1Mコンテキストを徹底解説【価格・性能比較つき】

Mistral Large 4とは?1兆パラメータMoE × 1Mコンテキストを徹底解説【価格・性能比較つき】

Mistral Large 4とは?1兆パラメータMoE × 1Mコンテキストを徹底解説【価格・性能比較つき】 はじめに:1兆パラメータなのに「安い」モデルが出た 2026年10月、Mistralが投下した「Le Chonk」 2026年10月6日、フランスのAIスタートアップMistral AIは「Mistral Large 4」をパブリックプレビューとして公開しました。社内ニックネームは 「L...

コメント

0/2000