概要

お客様のシステム

影響を受けていますか?

Webリクエストを処理するPHP(PHP-FPM、mod_phpを使用するApache、php-cgi、FrankenPHPまたはLiteSpeed)を運用しており、そのバージョンが8.2.35、8.3.36、8.4.27または8.5.12より古い場合は、影響を受けているものとみなしてください。これには、WordPress、Drupal、Magento、LaravelなどPHPで構築されたアプリケーションも含まれます。

TR7製品

TR7は影響を受けますか?

いいえ。TR7アプライアンスにはHTTPリクエストを処理するPHPコンポーネントがないため、TR7製品はこれらの脆弱性の影響を受けません。詳細はTR7は影響を受けますか?をご覧ください。

対応

今すぐ行うべきこと

  1. WebアプリケーションサーバーのPHPを更新し、すべてのPHPワーカーを再起動してください。
  2. 本日中に更新できない場合は、それらのサーバーに以下の一時的なPHP設定を適用してください。
  3. 更新が完了するまで、TR7 WAF-WAAPで基本保護設定を適用してください。その最初の設定は、PHPアプリケーションをBlocking modeにすることです。

基本情報

アドバイザリIDTR7-SA-2026-001
名称PHP2Shell
CVECVE-2026-109618(メモリ不足に起因するメモリ破損によるリモートコード実行)、
CVE-2026-109619(残存した古いグローバル状態によるリモートコード実行)
公式アドバイザリPHP Security Teamの発表
GHSA-w8hw-w9fx-j79w(CVE-2026-109618)
GHSA-6wmf-4rv5-p3rp(CVE-2026-109619)
深刻度CVSS v4.0 9.2、緊急(Critical)(PHP Security Team)
認証の要否不要
修正済みバージョンPHP 8.2.35、8.3.36、8.4.27、8.5.12
旧ブランチPHP Security Teamは、PHP 7.4、8.0、8.1向けのソースコードのバックポートを公開しました。Linuxディストリビューションは独自のパッチ適用済みパッケージを提供しています。
悪用状況悪用の試みが報告されています。2026年10月22日時点で、攻撃の成功事例は公には確認されていませんでした。
CISA KEV2026年10月21日時点のカタログには掲載されていません

経緯

  • 2026年10月20日 協調公開に先立ち、脆弱性の詳細が公になりました。
  • 2026年10月21日 PHPプロジェクトが修正版をリリースし、アドバイザリGHSA-w8hw-w9fx-j79wおよびGHSA-6wmf-4rv5-p3rpを公開しました。
  • 2026年10月21日~22日 悪用の試みが報告され、公開された概念実証コードが出現しました。

攻撃の仕組み

どちらの脆弱性もアプリケーションコードではなく、PHP自体に存在します。攻撃は、PHPが受信したリクエストをまだ読み込んでいる間、アプリケーションのコードが1行も実行される前に発生します。WordPress、プラグイン、または独自のコードを更新しても修正されません。

  • CVE-2026-109618は、PHPがメモリ不足に陥る瞬間を悪用します。攻撃者は、フォームデータやファイルアップロードの解析中にPHPに大量のメモリを使用させるリクエストを送信し、PHPを安全でない状態で停止させます。
  • CVE-2026-109619は、あるリクエストの後にPHPワーカー内に古いデータを残し、同じワーカーへの2回目のリクエストがそのデータを使用します。文書化されている経路の1つはPHPのsession upload progress機能を利用するもので、この機能はデフォルトで有効になっており、PHP_SESSION_UPLOAD_PROGRESSという名前のフォームフィールドによってトリガーされます。

これらの攻撃に使われるリクエストの大半はmultipart/form-data(ファイルアップロード)リクエスト、大きなリクエストボディ、繰り返し送信されるリクエストであるため、Webアプリケーションファイアウォールはその多くを把握し、制限できます。ただし、PHPのメモリ内部で起きていることは把握できません。

TR7は影響を受けますか?

これらの脆弱性はPHP自身のリクエスト処理層に存在し、PHPを実行するアプリケーションサーバーに影響します。TR7アプライアンスにはHTTPリクエストを処理するPHPコンポーネントがないため、TR7製品はこれらの脆弱性の影響を受けません。

今すぐ行うべき対応

対応が必要な場所は2つあります。PHPを実行するお客様自身のWebアプリケーションサーバーと、TR7 WAF-WAAPです。手順番号は各セクション内で個別に付けています。

お客様のサーバー上で

ステップ1:WebアプリケーションサーバーのPHPを更新する(唯一の完全な修正)

  1. Webアプリケーションを実行しているサーバーのPHPを8.2.35、8.3.36、8.4.27または8.5.12に更新するか、Linuxディストリビューションのパッチ適用済みパッケージをインストールしてください。ディストリビューションのパッケージは古いバージョン番号のままであることが多いため、パッケージの変更履歴でCVE番号を確認してください。
  2. すべてのPHPワーカーを再起動してください(PHP-FPMプール、Apache、LiteSpeed、長時間稼働するワーカー)。実行中のプロセスは、再起動するまで古いコードを使い続けます。
  3. 独自のPHPを含むコンテナイメージを再ビルドしてください。ホストを更新しても、イメージ内のPHPは更新されません。
  4. PHP 8.1以前は、PHPプロジェクトから更新が提供されなくなっています。サポート対象のブランチへのアップグレードを計画してください。

ステップ2:Webアプリケーションサーバーでの一時的なPHP設定(本日中に更新できない場合)

これらの設定は、Webアプリケーションを実行しているサーバーのPHP設定(php.iniまたはPHP-FPMプールの設定)で行います。これらの対策はPHP Security Teamが挙げているものです。特定の攻撃経路への露出を低減しますが、インストール環境を安全にするものではありません。

設定目的
session.upload_progress.enabled = 0CVE-2026-109619のsession upload progress経路を取り除きます。すべてのワーカーを再起動してください。PHP Security Teamは、この機能が不要であれば、パッチ適用後も無効のままにしておくことを推奨しています。
fatal_error_backtraces = 0(PHP 8.5)致命的エラーのバックトレース経路を取り除きます
post_max_size = 8M(アップロードなし)または32M(アップロードあり)とし、upload_max_filesizeはそれより小さくする攻撃者がPHPに使用させることのできるメモリ量を減らします
memory_limit = -1(php_admin_valueで設定)制御可能なメモリ上限エラーを取り除きます。ただしこの場合、1つのリクエストがサーバーのメモリをすべて使用できるようになります。コンテナまたはcgroupの制限を使用し、RLIMIT_ASやRLIMIT_DATAは決して使用しないでください

TR7 WAF-WAAP上で

PHPをすぐに更新できるのであれば、それが本当の修正です。すぐに更新できない場合は、更新が完了するまでの間、TR7のアップデートを一切必要とせずに、TR7 WAF-WAAPが既に備えているセキュリティ設定でPHPアプリケーションをこれらの攻撃から保護できます。ステップ1の3つの設定が基本保護です。ステップ2の追加対策は攻撃対象領域をさらに絞り込むものなので、アプリケーションに合うものを選択してください。設定はvServiceごとに適用し、まず本番環境以外のvServiceで試してください。

ステップ1:基本保護

1.1 WAFをBlocking modeにする

監視のみを行うWAFでは攻撃を阻止できません。WAFを最初に有効化するとLearning modeで開始されます。Monitor modeは記録のみを行います。各PHP vServiceについてWAF Mode画面を開き、Blocking modeになっていることを確認してください。

注意:切り替える前に、各フィールドで学習されたシグネチャ除外を確認してください。あるフィールドの除外がMax. owasp exclusionsの値を超えると、そのフィールドではシグネチャ検査が無効になります。

1.2 2つのカスタムルールを追加する

Signature & Rule Library画面(WAF → Signature & Rule Library → Add)で、以下の2つのルールを個別に追加してください。どちらもMonitor状態で開始し、Event Logsを確認した後にEnabledに変更してください。これらのルールは、WAFで保護されたすべてのvServiceに適用されます。

ルール1:Session upload progressフィールド

  • Pattern (Regex): PHP_SESSION_UPLOAD_PROGRESS
  • Inspection Scopes: FormおよびRaw
  • Score: Very High

CVE-2026-109619のsession upload progress経路をトリガーするフォームフィールドを検出します。この機能を正当に使用しているアプリケーションでは、この機能を必要とするアップロードパスのみを除外してください。

ルール2:PHPSESSIDフォームフィールド

  • Pattern (Regex): ^PHPSESSID$
  • Inspection Scopes: Form
  • Score: Very High

セッションIDをCookieではなくPHPSESSIDという名前のフォームフィールドで送信するリクエストを検出します。一部の攻撃経路はこの形式を使用し、正当なトラフィックではまれです。アプリケーションが別のセッション名(session.name)を使用している場合は、その名前を使用してください。

ルールを機能させるには:ルールは、リクエストに一致するページタイプのFormおよびRAW検査でスキャンされます。Form検査のないページタイプでは、フォームおよびファイルアップロードのボディはスキャンされません。

  • Any Pathsルール、および独自のFormまたはRAW検査を持つページタイプでは、OWASP checkをオンのままにしてください。
  • すべてのglobページタイプに、Add common rule for FormおよびAdd common rule for Rawボタンで独自のFormおよびRAW検査を追加してください。継承された設定に頼らないでください。
1.3 大きなボディと検査できないボディをブロックする

WAF Rules画面で、RAW検査に次の2つの設定を行います。

  1. Raw Body Sizeを、そのパスで必要な最大のボディサイズに設定します(バイト単位。例えば、アップロードのないパスでは8388608 = 8 MB、アップロードパスでは33554432 = 32 MB)。デフォルトの範囲では、最大256 MBのボディが許可されます。
  2. 未解析ボディのトグルをAllow unparsed bodyからBlock unparsed bodyに切り替えます。切り替えない場合、検査バッファに収まらないボディは、コンテンツ検査を一切受けずにBackend Serviceへ転送されます。

設定箇所は?WAFは、リクエストのパスに一致するページタイプの設定でのみリクエストを検査します。これら2つの設定は、Any Pathsルール、Check Fields列にRawと表示されるすべてのページタイプ、およびすべてのglobページタイプで行ってください。RAW検査のないglobページタイプには、まずAdd common rule for RawでRAW検査を追加してください。

注意:Raw Body Sizeは、Checks画面でStructure Checksがオンになっている間に適用されます。正当な大容量アップロードを先にテストしてください。長さを宣言せずに送信されたボディは、この制限では測定されません。アップロードパス以外のパスでは、2.1でブロックできます。

ステップ2:追加対策

これらの対策は基本保護を補完するものです。アプリケーションに合うものを選択してください。

2.1 不要な場所でファイルアップロードをブロックする

攻撃リクエストの大半はmultipart/form-data(ファイルアップロード)リクエストです。アプリケーション内でファイルを受け付けるパスが少数に限られる場合は、ロードバランサールールで、それ以外のすべてのパスへのmultipartリクエストをブロックしてください。このルールは2つの条件と1つのBlockアクションで構成されます。すべての画面には、左下のTR7ロゴから開くConfiguration Menuからアクセスできます。

A. 条件を作成する(Load Balancer → Conditions → Add)

  1. multipartリクエスト条件:Criteria = HTTP header、マッチング方式Includes、Header Name = Request → Content-Type、Query = multipart/form-data、Case Insensitiveをオン。Condition Nameにmultipart-requestなどの名前を入力し、Addで保存します。
  2. アップロードパス条件:Criteria = Path、マッチング方式Regexとし、Queryにファイルを受け付けるパスを入力します(例:^/(upload|media/upload))。Condition Nameにupload-pathsなどの名前を入力し、Addで保存します。

B. Blockアクションを作成する(Load Balancer → Actions → Add)

  1. Action Nameを入力し(例:block-multipart)、Action Type = Block、Execution Level = On Request、Deny Type = Standard、Status Code = 403とします。
  2. Conditionsで、multipart-requestと!upload-pathsを同じ条件グループ(デフォルトはand)で選択します。各条件はリストに2回表示されます。条件そのものと、!で始まるその否定(NOT)です。!upload-pathsは「アップロードパスのいずれでもない」ことを意味します。
  3. ブロックされたリクエストをカウントするためにHit Counterをオンにし、Addで保存します。

C. アクションをvServiceに追加する

  1. Load Balancer → Load Balancer vService ListでvServiceを選択してEditをクリックし、DetailsのActionsでアクションを選択して、Saveをクリックします。

D. 長さを宣言せずに送信されたボディもブロックする

  1. 別のHTTP header条件を作成します。マッチング方式Is present、Header Name = Request → Content-Length、Condition Nameは例えばhas-lengthとします。
  2. 2つ目のBlockアクション(On Request、Standard、403)を作成します。Conditionsで、定義済みのIf HTTP method is POST条件、!has-length、!upload-pathsを同じ条件グループで選択し、このアクションをvServiceのActionsフィールドに追加します。POST条件は必須です。これがないと、ボディのないGETリクエストもブロックされます。

1.3のサイズ制限では、長さを宣言せずに送信されたボディの実際のサイズを把握できません。このルールは、アップロードパス以外のパスにおいて、HTTP/1.1のストリーミング(chunked)アップロードと、長さが宣言されていないHTTP/2ボディの両方をカバーします。ボディがなくContent-LengthヘッダーもないPOSTリクエストもこのルールに一致するため、まず本番環境以外のvServiceで試してください。

確認:アップロードパス以外のパスに対するmultipartリクエスト(curl -s -o /dev/null -w '%{http_code}\n' -F 'a=b' https://www.example.com/)、HTTP/1.1のchunkedリクエスト(curl -s -o /dev/null -w '%{http_code}\n' --http1.1 -H 'Transfer-Encoding: chunked' -d 'a=b' https://www.example.com/)、および長さを宣言しないHTTP/2リクエスト(printf 'a=b' | curl -s -o /dev/null -w '%{http_code}\n' --http2 -X POST -T - https://www.example.com/)が403を受け取り、アップロードパスへのリクエストが通過することを確認してください。HTTP/1.1のテストには--http1.1が必要です。curlはhttps上ではデフォルトでHTTP/2を使用し、HTTP/2ではTransfer-Encodingを送信しないためです。カウンターはvServiceダッシュボードのAction Hitsタブに表示されます。

注意:条件が1つも選択されていないBlockアクションは、vServiceへのすべてのリクエストに適用されます。アップロードパスを漏れなくすべて列挙し、まず本番環境以外のvServiceでルールを試してください。

2.2 クライアントごとのPOSTリクエストを制限する

このルールは標的型攻撃を阻止するものではありません。エクスプロイトはごく少数のリクエストで成功する可能性があります。ただし、多数の標的を試す自動化ツールのコストを引き上げます。このルールは各クライアントIPのPOSTリクエストをカウントし、しきい値を超えたクライアントのPOSTリクエストを429でブロックします。カウンターがしきい値を下回ると、ブロックは自動的に解除されます。

A. カウンターアクションを作成する(Load Balancer → Actions → Add)

  1. Action Nameを入力し、Action Type = Advanced Traffic Inspection、Fields to Track = Client IP address、Traffic Tag = 例えばpost-rate(3~20文字。英字、数字、-、_)、Tracking Period = 1分とします。
  2. Conditionsで定義済みのIf HTTP method is POST条件を選択し、Addで保存します。これにより、POSTリクエストのみがカウントされます。

B. しきい値条件を作成する(Load Balancer → Conditions → Add)

  1. Criteria = Tracking Condition、Tracked Table = post-rate、Tracking Criteria = HTTP requestsとし、Tracking Operatorでしきい値を指定します(例:> 100)。Addで保存します。

C. Blockアクションを作成する(Load Balancer → Actions → Add)

  1. Action Type = Block、Execution Level = On Request、Deny Type = Standard、Status Code = 429とします。
  2. Conditionsで、ステップ3のしきい値条件とIf HTTP method is POSTを同じ条件グループ(デフォルトはand)で選択します。POST条件がないと、しきい値を超えたクライアントのGETリクエストもブロックされます。Addで保存します。

D. アクションをvServiceに追加する

  1. vServiceのEditフォームのDetails → Actionsで、カウンターアクションを1番目、Blockアクションを2番目に選択し、Saveをクリックします。アクションはリストの順序で実行されます。

確認:vServiceのLogs & Trackingタブで、Logs Typeリストからカウンターアクションのトラッキングテーブルを選択すると、クライアントごとのPOSTカウンターが表示されます。しきい値はアプリケーションの通常のトラフィックに基づいて設定してください。正当なクライアント(例えばAPIを使用するシステムや、共有の送信元IPの背後にある組織)の1分あたりのPOST数をテーブルで観察し、それを上回る値にしきい値を設定します。

2.3 L7 DDoS保護をActiveに設定する

ライセンスにBot/DDoS保護が含まれている場合、L7 DDoS ProtectionのSource IP Request Protectionは、単一の送信元アドレスが一定期間内に送信できるリクエストの総数を制限します。2.2とは異なり、すべてのリクエストをカウントし、追加のルールは必要ありません。

  1. vServiceのEditフォームで、DetailsのL7 DDoS & Threat Protectionを選択し、Saveをクリックします(オンになっていない場合)。保護をオンにすると、L7 DDoS ProtectionはMonitorモードで開始されます。このモードでは、制限違反はイベントとして記録されるだけです。
  2. Left Monitor Panel → Bot/DDoS Protected vServices → vService → Bot/DDoS Managementで、L7 DDoS ProtectionカードのEditリンクをクリックします。
  3. DDoS Protection = Activeに設定し、Editボタンで保存します。
  4. カード上で、Source IP Request Protectionブロックの鉛筆アイコンをクリックします。Time Window(デフォルト10秒)、Request Limit(デフォルト1000)、Limit Action(デフォルトはShow Captcha。Blockも選択可能)をアプリケーションのトラフィックに合わせて設定し、Editボタンで保存します。

注意:Activeに切り替える前に、Monitorモードでしばらくイベントを監視してください。Request Limitを下げる際にも、同様の観察を繰り返してください。

攻撃の標的になったかどうかを確認する

検知と監視を参照してください。悪用の試みは一般公開前から報告されていたため、2026年10月17日以降のログを確認してください。

WAFにできること、できないこと

WAFにできることWAFにできないこと
session upload progressフィールドなど、既知のリクエスト形態をブロックするPHP内部の脆弱なコードを修正する
ボディサイズ、アップロードパス、リクエストレートを制限するPHPプロセス内部のメモリ使用量を測定する
アップロードが不要なパスでアップロードをブロックするWAFを経由せずにサーバーに到達するリクエストを把握する
ブロックされたリクエストやレート制限されたリクエストを記録するサーバー上で既に実行されたコードを元に戻す

WAFルールは更新までの時間を稼ぐものであり、恒久的な修正はPHPの更新です。これらの保護を機能させるには、PHPアプリケーションへのすべてのトラフィックがTR7 WAF-WAAPを経由する必要があります。

検知と監視

TR7上で

  • WAFで保護された各vServiceのEvent Logs画面で、カスタムルールでレコードを絞り込み、一致したフィールドとスコアを確認してください。
  • 同じ画面で、ボディサイズのルールおよび未解析ボディのルールによってブロックされたリクエストを確認してください。
  • 追加対策を適用した場合は、vServiceダッシュボードのAction Hitsタブでロードバランサールールのカウンターを、Logs & TrackingタブのトラッキングテーブルでPOSTレート制限に達したクライアントを監視してください。

お客様のサーバー上で

  • PHPのエラーログで、Allowed memory size ... exhaustedなどのエラー、ワーカーのクラッシュ、繰り返し発生するHTTP 500レスポンスを検索してください。特に、大きなmultipart/form-dataリクエストの直後に発生したものに注意してください。
  • レスポンスに、異常に大きい、または不正な形式のPHPSESSID Cookieがないか確認してください。
  • Webルートに新規作成または変更されたファイルがないか確認し、Webサーバーユーザーによって起動された想定外のプロセス、新しいcronジョブ、想定外の外向き接続がないか調べてください。

よくある質問

いいえ。TR7アプライアンスにはHTTPリクエストを処理するPHPコンポーネントがないため、TR7製品はこれらの脆弱性の影響を受けません。「TR7は影響を受けますか?」を参照してください。

これらの脆弱性を完全に防げるWAFはありません。TR7 WAF-WAAPは攻撃対象領域を縮小し、既知の攻撃経路をブロックします。完全な修正はPHPの更新のみです。

PHP2Shellに対しては、TR7 WAF-WAAP 1.2の2つのカスタムルールを使用してください。これらのルールは、WAFで保護されたすべてのvServiceに直ちに適用されます。

いいえ。脆弱性はPHPランタイムに存在します。PHP自体を更新するか、ホスティングプロバイダーに更新を依頼してください。

あり得ます。ボディサイズの制限、アップロードのブロック、カスタムルールは、正当なアップロードやフォームに影響する可能性があります。WAFルールはMonitor modeで開始し、Event Logsを確認してからBlocking modeに切り替えてください。ロードバランサールール(2.1、2.2)は、まず本番環境以外のvServiceで試してください。

更新履歴

  • 2026年10月23日 初版公開。

参考資料

これらの設定の適用にサポートが必要ですか?

TR7サポートチームは、お客様のWAF設定を確認し、これらの保護の導入を支援できます。TR7の担当者、またはsupport@tr7.comのTR7サポートチームまでお問い合わせください。