Amazon Web Services ブログ

AWS WAF を使用した PHP2Shell RCE 脆弱性 (CVE-2026-109618 および CVE-2026-109619) の緩和策

本ブログは 2026 年 10 月 21 日に公開された AWS Blog “Using AWS WAF to apply mitigations for PHP2Shell RCE vulnerabilities (CVE-2026-109618 and CVE-2026-109619)” を翻訳したものです。

2026 年 10 月 21 日、PHP プロジェクトは、PHP コアランタイムに存在する 2 件の重大なリモートコード実行 (RCE) 脆弱性に対して緊急の修正をリリースしました。これらの脆弱性は CVE-2026-109618 および CVE-2026-109619 として追跡されており、総称して PHP2Shell と呼ばれています。いずれも CVSS v4.0 で 9.2 (Critical: 緊急) と評価されており、認証されていない攻撃者が脆弱なサーバー上でコードを実行できます。修正済みのリリースは PHP 8.5.12、8.4.27、8.3.36、8.2.35 です。

完全な修正はパッチ適用以外になく、PHP のアップグレードを最優先で進める必要があります。ただし、サーバーのフリート全体へのパッチ適用には時間がかかります。PHP が稼働している場所の棚卸し、メンテナンスウィンドウの調整、新しいビルドでのアプリケーションのテストが必要になるためです。本記事では、AWS WAF を使用して、パッチ適用が完了するまでの間、確認済みの攻撃経路への露出を低減する方法を紹介します。ブロックすべきリクエストパターン、AWS WAFv2 でのルールの記述方法、正当なトラフィックに影響を与えずにルールをデプロイする方法を説明します。また、誤った安心感を抱かないよう、AWS WAF による保護の限界についても説明します。Amazon の脅威インテリジェンスが脆弱性の公表前に PHP2Shell の悪用をどのように検出したかについては、「Amazon Threat Intelligence が PHP2Shell の脆弱性公開前の悪用を MadPot で特定」を参照してください。AWS サービスの状況と AWS が推奨する AWS WAF ルールについては、「AWS Security Bulletin 2026-143-AWS」を参照してください。

重要: 完全な修正はパッチ適用以外になく、PHP のアップグレードを最優先で進める必要があります。


脆弱性の概要

PHP2Shell の 2 つの脆弱性はいずれも認証不要の RCE であり、アプリケーションコードが実行される前に PHP が multipart/form-data リクエスト (ブラウザがファイルアップロードに使用するリクエスト形式) を処理する方法に起因しています。そのため、本記事の AWS WAF ルールでは、multipart トラフィック、リクエスト本文のサイズ、セッションアップロード進捗 (session upload progress) フィールドに焦点を当てています。大まかに言えば、CVE-2026-109618 は、リクエストの処理中に PHP がメモリ不足 (out-of-memory) に陥った際にメモリ破壊を引き起こします。CVE-2026-109619 は、あるリクエストが残した古いデータを、同じワーカープロセス上の後続のリクエストが再利用してしまう脆弱性です。根本原因の分析、影響を受けるバージョン、PHP プロジェクト自身のガイダンスについては、PHP の公式アドバイザリとリリースアナウンスを参照してください。

対応策における AWS WAF の位置付け

今回のケースでは、AWS WAF は多層防御のための制御であり、PHP のアップグレードに代わるものではありません。PHP のアドバイザリでも、パッチ適用済みのリリースへの更新が唯一の完全な緩和策であると明言されています。後述するとおり、2 つの脆弱性のうち 1 つは、その大部分がウェブアプリケーションファイアウォールでは対処できない範囲にあります。本記事のルールは、パッチ適用が完了するまでの間の露出を低減する緩和策として扱い、パッチ適用後は削除するか、補助的な制御として維持してください。

AWS WAF はエッジで HTTP リクエストを検査します。multipart 本文の内部構造は解析せず、PHP ワーカーのメモリやサーバー側の設定も把握できません。次の表に、各攻撃要素に対して AWS WAF が緩和策として機能するかどうかを示します。

攻撃要素

AWS WAF の対応範囲

multipart POST に含まれるセッションアップロード進捗フィールド (PHP_SESSION_UPLOAD_PROGRESS、PHP のアップロード追跡機能を有効にするフォームフィールド)

対応可能。このフィールドを含むリクエストを対象としたルールでブロックできます。

multipart アップロード経路 (multipart/form-data、ファイルアップロードに使用されるリクエストタイプであり、両方の脆弱性の侵入口)

対応可能。ただし、アプリケーションに正当な multipart アップロードがない場合に限ります。ブロック対象: multipart/form-data.

サイズ超過の本文によるメモリ不足状態

一部対応。リクエスト本文のサイズに上限を設定します。ただし、上限内に収まるヘッダー増幅 (header amplification: 多数の小さなパートヘッダーにより、送信時のサイズをはるかに上回るメモリが消費されるもの) は検出できません。

同じワーカー (多数のリクエストの処理に再利用される PHP プロセス) に対する繰り返しの試行

対応可能。レートベースのルールにより、エクスプロイトに必要な大量のリクエスト送信を抑制できます。

プロデューサー (producer) として機能する fatal_error_backtraces (リクエストをまたいでクラッシュトレースの状態を保持する PHP 8.5 の設定)

対応不可。これはサーバーの構成設定です (fatal_error_backtraces=0)。

コンシューマー (consumer) として機能する、無効または非推奨の INI 設定に関する診断 (不正な構成設定の適用時に PHP が出力する警告)

対応不可。この経路はクライアントからの HTTP 通信ではなく、サーバー側で実行されます。

アプリケーションが multipart アップロードを受け付けない場合は、multipart/form-data をブロックするルールをエッジに適用することで、あらゆるアプリケーションに対して悪用可能な、multipart 処理でメモリ不足を引き起こす攻撃経路と、セッションアップロード進捗のトリガーを排除できます。これは、パッチ適用期間中の多層防御として機能します。

アプリケーションで multipart アップロードを使用している場合、AWS WAF でリスクは低減できますが、脆弱性を解消することはできません。ヘッダー増幅 (数キロバイトのパートヘッダーが、PHP 内部ではるかに大きなメモリに展開されるもの) はサイズ制限内に収まるうえ、ファイアウォールは本文の各パート内にあるヘッダーを解析できないためです。この場合は、PHP のアップグレードを優先し、後述するサーバー側の緩和策を適用してください。

AWS WAF ルールの実装

以下のルールは AWS WAFv2 の JSON 形式です。各ルールを、PHP ワークロードの前段にある Amazon CloudFront ディストリビューション、Application Load Balancer、または Amazon API Gateway ステージに関連付けられた AWS WAF 保護パック (ウェブ ACL) にデプロイしてください。

重要: 変更を実装する前に、AWS WAF のログ記録に関するガイダンスに沿って WAFv2 のログ記録が設定されていることを確認してください。すべてのルールはまず Count モードで開始し、正当なトラフィックに一致しないことを確認してから Block に切り替えてください。


リクエスト本文の検査サイズ制限

AWS WAF は、リクエスト本文を一定のサイズまで検査します。Application Load Balancer と AWS AppSync では、この制限は 8 KB で固定されています。CloudFront や API Gateway などの AWS サービスでは、デフォルトは 16 KB で、以下のようにウェブ ACL の AssociationConfig を使用して 32、48、または 64 KB に引き上げることができます。本文検査サイズ制限を超えた部分は、サイズ超過として扱われます。本文サイズのルールで適用できる上限は検査対象のサイズまでであるため、デプロイするルールに合わせて制限を選択してください。

aws wafv2 update-web-acl ... --association-config \
'RequestBody={CLOUDFRONT={DefaultSizeInspectionLimit=KB_16}}'

AWS WAF ルール

このルールは両方の CVE を対象とし、AndStatement 内の 3 つの条件すべてが同時に満たされた場合にのみリクエストをブロックします。

  1. メソッドが POST と完全に一致する – HTTP メソッドで照合 (変換なし)
  2. PHP のセッション識別子が存在する (ネストされた OrStatement により、次のいずれかのサブ条件を満たせば成立)

    • PHPSESSID が Cookie のキーとして存在する (すべての Cookie を対象に、キーを完全一致で照合)、または
    • PHPSESSID がリクエスト本文のいずれかの場所に存在する (部分一致)
  3. 本文に PHP_SESSION_UPLOAD_PROGRESS が含まれる – PHP のセッションアップロード進捗機能を有効にするフォームフィールド

このルールと併せて、サーバー側で session.upload_progress.enabled=0 を設定し、この機能を無効にしてください。

{
  "Name": "PHP2Shell",
  "Priority": 0,
  "Statement": {
    "AndStatement": {
      "Statements": [
        {
          "ByteMatchStatement": {
            "SearchString": "POST",
            "FieldToMatch": {
              "Method": {}
            },
            "TextTransformations": [
              {
                "Priority": 0,
                "Type": "NONE"
              }
            ],
            "PositionalConstraint": "EXACTLY"
          }
        },
        {
          "OrStatement": {
            "Statements": [
              {
                "ByteMatchStatement": {
                  "SearchString": "PHPSESSID",
                  "FieldToMatch": {
                    "Cookies": {
                      "MatchPattern": {
                        "All": {}
                      },
                      "MatchScope": "KEY",
                      "OversizeHandling": "CONTINUE"
                    }
                  },
                  "TextTransformations": [
                    {
                      "Priority": 0,
                      "Type": "NONE"
                    }
                  ],
                  "PositionalConstraint": "EXACTLY"
                }
              },
              {
                "ByteMatchStatement": {
                  "SearchString": "PHPSESSID",
                  "FieldToMatch": {
                    "Body": {
                      "OversizeHandling": "CONTINUE"
                    }
                  },
                  "TextTransformations": [
                    {
                      "Priority": 0,
                      "Type": "NONE"
                    }
                  ],
                  "PositionalConstraint": "CONTAINS"
                }
              }
            ]
          }
        },
        {
          "ByteMatchStatement": {
            "SearchString": "PHP_SESSION_UPLOAD_PROGRESS",
            "FieldToMatch": {
              "Body": {
                "OversizeHandling": "CONTINUE"
              }
            },
            "TextTransformations": [
              {
                "Priority": 0,
                "Type": "NONE"
              }
            ],
            "PositionalConstraint": "CONTAINS"
          }
        }
      ]
    }
  },
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "PHP2Shell"
  }
}

検討すべきその他の AWS WAF ルール

アプリケーションでアップロードを使用しない場合に multipart リクエストをブロックする

注: このルールを Block モードで実装すると、ファイルアップロードを必要とするアプリケーションが動作しなくなります。アプリケーションでファイルアップロードが不要な場合は、multipart/form-data をブロックすることで、両方の CVE について、あらゆるアプリケーションに対して悪用可能な、multipart 処理でメモリ不足を引き起こす攻撃経路をエッジで排除できます。

名前を指定した単一のヘッダーは 8 KB のヘッダー上限の対象外で、全体が検査されます。そのため、Content-Type ヘッダーでの照合は確実に機能します。

{
  "Name": "Block-Multipart-FormData",
  "Priority": 1,
  "Action": { "Count": {} },
  "Statement": {
    "ByteMatchStatement": {
      "FieldToMatch": { "SingleHeader": { "Name": "content-type" } },
      "PositionalConstraint": "CONTAINS",
      "SearchString": "multipart/form-data",
      "TextTransformations": [ { "Priority": 0, "Type": "LOWERCASE" } ]
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellBlockMultipart" }
}

リクエスト本文のサイズに上限を設定する

本文サイズに上限を設定すると、CVE-2026-109618 の原因となるメモリ不足状態と、それによって残る可能性のある古い状態を抑制できます。サイズ制約と併せて OversizeHandling: MATCH を使用すると、本文検査サイズ制限を超える本文も含め、しきい値より大きい本文をすべてブロックできます。N バイトの上限を適用するには、ウェブ ACL の本文検査サイズ制限を N 以上にする必要があります。なお、サイズ制約で Content-Length の数値に上限を設定することはできません。サイズ制約が測定するのはヘッダー値の文字列の長さであり、値が表す数値ではないためです。アプリケーションに正当な大容量アップロードがある場合は、URI パスに対する AndStatement を使用して、このルールの対象をアップロード以外のパスに限定してください。限定しない場合、それらのアップロードが動作しなくなります。

{
  "Name": "Block-Oversize-Body",
  "Priority": 3,
  "Action": { "Count": {} },
  "Statement": {
    "SizeConstraintStatement": {
      "FieldToMatch": { "Body": { "OversizeHandling": "MATCH" } },
      "ComparisonOperator": "GT",
      "Size": 8192,
      "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ]
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellBlockOversizeBody" }
}

注: AWSManagedRulesCommonRuleSet マネージドルールグループを既に使用している場合、そのグループに含まれる SizeRestrictions_BODY ルールが、デフォルトで 8 KB を超える本文をブロックします。特定のマネージドルールが正当なトラフィックに影響する場合は、グループ全体を無効にするのではなく、そのルールのみを Count にオーバーライドしてください。

繰り返しの試行をレート制限する

POST リクエストにレートベースのルールを適用すると、攻撃者が送信できるリクエスト量を抑え、ワーカーへの過負荷によって脆弱性がトリガーされる可能性を下げることができます。また、古い状態を悪用する経路が成立するには、プロデューサーのリクエストとコンシューマーのリクエストが同じワーカーに到達する必要があります。このルールは、リクエストごとにワーカーをリサイクルするサーバー設定 pm.max_requests=1 を補完するものです。

{
  "Name": "RateLimit-Posts",
  "Priority": 4,
  "Action": { "Count": {} },
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "EvaluationWindowSec": 60,
      "AggregateKeyType": "IP",
      "ScopeDownStatement": {
        "ByteMatchStatement": {
          "FieldToMatch": { "Method": {} },
          "PositionalConstraint": "EXACTLY",
          "SearchString": "POST",
          "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ]
        }
      }
    }
  },
  "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "PHP2ShellRateLimitPosts" }
}

AWS WAF を補完するサーバー側の緩和策

以下のホストとランタイムの変更は、ウェブアプリケーションファイアウォールが検査する HTTP レイヤーより下にある CVE-2026-109619 の要素に対処するものです。そのため、これらの要素は、そもそもファイアウォールの対象範囲外にあります。防御におけるホストおよびランタイムのレイヤーとして、AWS WAF ルールと併せて適用してください。

  • PHP を 8.5.12、8.4.27、8.3.36、または 8.2.35 にアップグレードします。これが唯一の完全な修正です。PHP 8.1 以前はアップストリームでのサポートが終了しています。ディストリビューションまたは長期サポートベンダーにバックポートされた修正があるかを確認するか、サポート対象のブランチへの移行を計画してください。
  • PHP レベルで CVE-2026-109618 に対処します。アプリケーションが上書きできないように memory_limit=-1 を設定し、post_max_size は小さい値に抑えます (アプリケーションがアップロードを受け付けない場合は 8M、受け付ける場合は 32M)。メモリの上限はコンテナまたは cgroup の制限で適用してください。RLIMIT_AS や RLIMIT_DATA は脆弱なメモリ不足経路をトリガーするため、決して使用しないでください。
  • PHP 8.5 で fatal_error_backtraces=0 を設定し、すべてのワーカーを再起動します。これにより、リクエストをまたいでクラッシュトレースの状態を保持する設定が無効になります。この設定は、脆弱性をトリガーする方法として確認されているものの 1 つです。
  • サーバー側で session.upload_progress.enabled=0 を設定し、すべてのワーカーを再起動します。これにより、もう 1 つの確認済みのトリガーであるアップロード追跡機能が無効になります。この機能は、パッチ適用後も無効のままにしておくことをお勧めします。
  • 設定には php.ini、FPM プール、またはサーバー起動時の構成を、リクエストごとの INI オーバーライド (リクエスト単位で設定を適用する .htaccess、php_value、または FastCGI の PHP_VALUE) よりも優先して使用してください。また、診断警告が発生しないよう、廃止されたディレクティブは削除してください。
  • 致命的なエラーと実行タイムアウトを解消します。対象は、アップロード、インポート、エラーページ、シャットダウン、シリアル化、拡張機能のパスなど、攻撃者が到達可能なルートです。
  • パフォーマンス上問題がなければ、pm.max_requests=1 を設定します。これにより、各ワーカープロセスは 1 つのリクエストを処理するたびにリサイクルされ、古いデータを残すリクエストと、そのデータを再利用する後続のリクエストとのつながりが断たれます。
  • エラーログ記録を有効にします (log_errors=On、有効な出力先を指定した error_log、error_reporting=E_ALL)。そのうえで、Apache、FPM、またはプロキシのログを確認し、攻撃者が制御可能なルートで警告、非推奨の通知、致命的なエラー、タイムアウトが繰り返し発生していないかを調べてください。エラーが出ていないからといって、安全であるとは限りません。

開始方法

次の手順で対応を開始してください。

  1. PHP が稼働している場所と、使用中のバージョンおよびサーバー API (mod_php、FPM、FrankenPHP、LSAPI) を棚卸しします。また、リクエスト本文を受け付けるパブリックエンドポイントを特定します。
  2. 各アプリケーションが multipart アップロードを使用しているかどうかを確認します。これにより、multipart リクエストをブロックする AWS WAF ルールをデプロイできるかどうかが決まります。
  3. 各 PHP ワークロードの前段にあるウェブ ACL を作成または更新し、該当するルールを Count モードで追加します。ルールで必要な場合は、CloudFront または API Gateway の本文検査サイズ制限を引き上げます。
  4. 各ルールのサンプリングされたリクエストと Amazon CloudWatch メトリクスを監視し、正当なアップロードや大容量の JSON 本文を含む POST リクエストがルールに一致していないことを確認します。
  5. メトリクスに問題がなければ、ルールを Block に切り替えます。セッションアップロード進捗フィールドのルールと multipart ルールが、本文サイズルールとレートベースのルールより先に評価されるよう、優先度を設定します。
  6. 無害な multipart/form-data の POST、設定したサイズ上限を超える本文、PHP_SESSION_UPLOAD_PROGRESS を含むリクエストでテストします。403 レスポンスが返され、一致したルールのメトリクスが記録されることを確認します。
  7. 並行して、PHP のアップグレードと構成の緩和策を適用します。フリートへのパッチ適用が完了したら、AWS WAF ルールを削除するか、補助的な制御として維持します。

まとめ

PHP2Shell 脆弱性 (CVE-2026-109618 および CVE-2026-109619) は、アプリケーションコードが実行される前の段階で PHP に到達する、認証不要の RCE 脆弱性です。AWS WAF は、パッチ適用期間中のアタックサーフェスの縮小に役立ちます。具体的には、セッションアップロード進捗フィールドのブロック、アップロードが想定されない場合の multipart リクエストのブロック、リクエスト本文サイズの上限設定、繰り返しの試行のレート制限です。これらの緩和策は露出の低減に役立ちますが、脆弱性そのものを解消するものではありません。PHP を修正済みのリリースにアップグレードし、サーバー構成の変更を適用してください。AWS WAF ルールは修正そのものではなく、それらの修正を支えるエッジのレイヤーとして位置付けてください。

ここで使用したルールタイプの詳細については、AWS WAF ドキュメントのウェブ ACL の本文検査サイズ制限、サイズ超過のリクエストコンポーネントの処理、およびサイズ超過の HTTP リクエスト本文の処理に関するページを参照してください。脆弱性の詳細については、PHP アドバイザリ GHSA-w8hw-w9fx-j79w および GHSA-6wmf-4rv5-p3rp、PHP のセッションアップロード進捗のマニュアルを参照してください。

Alex Waddell

Alex Waddell

Alex Waddell は、AWS の Worldwide Specialist Organization でセキュリティを専門とする Principal Solutions Architect で、スコットランドを拠点としています。1999 年からセキュリティ分野に携わり、2021 年に AWS に入社しました。EMEA 全域のお客様とともに、クラウドセキュリティアーキテクチャ、アイデンティティ、脅威検出、アプリケーションセキュリティに取り組んでいます。仕事以外では、世界各地のラム酒の飲み比べ (Alex はウイスキーを好まない珍しいスコットランド人の 1 人です)、地元の森の小道での犬の散歩、旅行を楽しんでいます。

Lawton Pittenger

Lawton Pittenger

Lawton は、ニューヨーク市を拠点とする AWS の Worldwide Security Specialist Solutions Architect です。効果的なネットワークセキュリティ制御の設計と実装について、お客様を支援することを専門としています。AWS では、幅広いお客様と協力するとともに、サービスチームと緊密に連携し、お客様のニーズとフィードバックに基づいてセキュリティサービスの継続的な改善を推進しています。仕事以外では、スケートボード、スノーボード、自然の中で過ごすことを楽しんでいます。

Ian Olson

Ian Olson

Ian は AWS の Senior Security Specialist Solutions Architect です。お客様がセキュリティサービスを自動化し、DDoS やウェブの脆弱性を悪用した攻撃などの脅威から環境を保護できるよう支援しています。インテリジェントオートメーションを通じて、あらゆる規模の組織に合わせたセキュリティソリューションを提供しています。仕事以外では、2 人の幼い子どもと過ごす時間を大切にしています。

本ブログは Security Solutions Architect の 中島 章博 が翻訳しました。