PHP2Shell緊急緩和策とパッチ適用ガイド: session.upload_progress無効化とEOLバージョンのバックポート手順
PHP2Shell緊急緩和策とパッチ適用ガイド: session.upload_progress無効化とEOLバージョンのバックポート手順
<time datetime="2026-10-23">検証日: 2026年10月23日</time> · 運用レベル: 即時対応必須 (P0)
PHP2Shell(CVE-2026-109618 および CVE-2026-109619)の公開を受け、世界中のホスティング事業者およびインフラ管理者は緊急の対応を迫られています。本稿では、本番環境のサービス停止を伴わずにリスクを完全にゼロ化するダウンタイムゼロの緩和策から、公式サポートが終了したEOLバージョン(PHP 8.1、8.0、7.4)に対するソースコードレベルのバックポートパッチ作成手順までを網羅的に解説します。
1. 優先度マトリクスと対応フロー
| 優先度 | 対象システム | 推奨アプローチ | 所要時間目安 | サービス影響 |
|---|---|---|---|---|
| P0 (最優先) | 全てのPHP稼働サーバー | session.upload_progress.enabled = Off 設定 | 5分以内 | ダウンタイムなし (Reload) |
| P1 (境界防御) | Nginx / HAProxy / Cloudflare | WAF仮想パッチおよびマルチパート検証ルールの導入 | 15分 | ダウンタイムなし |
| P2 (恒久対策) | サポート期間内PHP (8.2〜8.5) | 公式修正版パッケージへのアップグレード | 30分〜1時間 | 計画保守リロード |
| P3 (延命対策) | EOLブランチ (PHP 8.1 / 8.0 / 7.4) | ディストリビューションLTSパッチ適用または自主ビルド | 2時間〜 | 要検証・再ビルド |
2. 5分で完了するダウンタイムゼロの緊急緩和策
本脆弱性の根本原因である cached_post_bytes の二重解放・Use-After-Freeは、PHPのコア拡張機能である session.upload_progress がリクエスト解析時に有効化されている場合にのみトリガーされます。したがって、この機能を無効化することにより、脆弱なC言語コードパス自体の実行を物理的に遮断できます。
ステップ 1: 全ての SAPI 設定ファイルの特定
PHP-FPM、CLI、Apache(mod_php)それぞれで異なる php.ini が読み込まれている場合があります。以下のコマンドで設定ファイルの位置を特定します。
php --ini | grep "Loaded Configuration File"
find /etc/php/ -name "php.ini" 2>/dev/null
ステップ 2: 設定の無効化と上書き
設定ファイルを開き、以下のディレクティブを設定します(コメントアウト ; が付いている場合は外してください):
; /etc/php/8.x/fpm/php.ini および /etc/php/8.x/cli/php.ini
[Session]
session.upload_progress.enabled = Off
session.upload_progress.cleanup = On
もし多数のサーバーを一括管理している場合、専用の優先設定ファイル(Drop-in ini)を配置するのが最も確実です:
echo -e "; Fix CVE-2026-109618 & CVE-2026-109619\nsession.upload_progress.enabled = Off" | sudo tee /etc/php/8.3/mods-available/php2shell-fix.ini
sudo phpenmod php2shell-fix
ステップ 3: サービスのリロード(ダウンタイムゼロ)
restart ではなく reload を使用することで、処理中のHTTPリクエストを切断することなく安全に設定を再読込します。
# Ubuntu / Debian
sudo systemctl reload php8.3-fpm
# RHEL / CentOS / Rocky Linux / AlmaLinux
sudo systemctl reload php-fpm
# 構文チェック
sudo php-fpm8.3 -t
3. リバースプロキシ・WAF層による境界フィルタリング
バックエンドのPHPサーバーが多数存在し、一括設定変更に時間がかかる場合は、ロードバランサーやリバースプロキシ(Nginx)層で攻撃リクエストを即座に破棄します。
Nginx 設定例 (/etc/nginx/conf.d/block_php2shell.conf)
PHP2Shellのエクスプロイトペイロードは、multipart/form-data 形式のPOSTボディ内に PHP_SESSION_UPLOAD_PROGRESS フィールドを埋め込みます。
# リクエストボディのバッファリングとヘッダー検査
map $http_content_type $is_multipart {
default 0;
~*^multipart/form-data 1;
}
server {
listen 443 ssl http2;
server_name example.com;
# アップロード進捗パラメータを悪用した攻撃の遮断
# (LuaモジュールまたはCoraza/ModSecurityが利用可能な場合)
location / {
# ModSecurity 仮想パッチ
# SecRule REQUEST_BODY "@rx (?i)PHP_SESSION_UPLOAD_PROGRESS" \
# "id:10261091,phase:2,deny,status:403,log,msg:'PHP2Shell CVE-2026-109618 Exploit Attempt'"
proxy_pass http://php_backend;
}
}
AWS WAF / Cloudflare WAF ルール
WAF管理画面にて、以下のカスタムルールを作成します:
- 一致条件: HTTP Request Body contains
PHP_SESSION_UPLOAD_PROGRESS(Case-Insensitive) - アクション: Block (HTTP 403)
- 優先度: 最上位 (Priority 1)
4. EOL版PHP (8.1 / 8.0 / 7.4) のバックポート修正
PHP 8.1以前は公式アップストリームのセキュリティサポートが終了(End of Life)しているため、apt upgrade では修正版が提供されません。Ubuntu Pro等の有償延長サポートを利用していない場合は、以下のパッチを適用してPHPランタイムを再ビルドする必要があります。
C言語コア修正差分 (ext/session/session.c)
以下のパッチは、アップロード完了またはセッション初期化中断時に、残存する未開放ポインタをNULLクリアし、二重解放(Double-Free)およびUse-After-Freeを防止するものです。
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1480,6 +1480,12 @@ PHP_SESSION_API void php_session_cleanup(void)
if (PS(cached_post_bytes)) {
efree(PS(cached_post_bytes));
PS(cached_post_bytes) = NULL;
+ }
+
+ /* CVE-2026-109619: Prevent dangling pointer in global session state */
+ if (PS(upload_progress_key)) {
+ zend_string_release(PS(upload_progress_key));
+ PS(upload_progress_key) = NULL;
}
}
ビルドとインストールの検証手順
# ビルド依存パッケージの取得
sudo apt-get build-dep php8.1
# ソースの取得とパッチ適用
git clone --branch PHP-8.1.31 https://github.com/php/php-src.git
cd php-src
patch -p1 < /path/to/php2shell-mitigation.patch
# 最適化フラグをつけてコンパイル
./buildconf --force
./configure --prefix=/opt/php-8.1-secure \
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
--with-openssl \
--with-zlib \
--with-curl
make -j$(nproc)
make test
sudo make install
5. 是正完了の自動監査スクリプト
対応が確実に完了したことを証明するため、以下のBashワンライナーを全ノードで実行し、レポートを生成します。
#!/usr/bin/env bash
echo "=== PHP2Shell Audit Report ==="
echo "Hostname: $(hostname)"
echo "Date: $(date -u)"
PHP_VER=$(php -r "echo PHP_VERSION;")
echo "Installed PHP Version: ${PHP_VER}"
PROGRESS_STATE=$(php -r "echo ini_get('session.upload_progress.enabled') ? 'VULNERABLE (On)' : 'PROTECTED (Off)';")
echo "Mitigation Status: ${PROGRESS_STATE}"
if [ "${PROGRESS_STATE}" == "PROTECTED (Off)" ]; then
echo "Result: [PASS] System is protected against unauthenticated PHP2Shell RCE."
exit 0
else
echo "Result: [FAIL] Immediate action required: set session.upload_progress.enabled = Off"
exit 1
fi