AWS WAF のマネージドルール PHP2Shell_BODY をカスタムルールと比べ、CloudFront の 64 KB ボディ検査で試してみた

AWS WAF のマネージドルール PHP2Shell_BODY をカスタムルールと比べ、CloudFront の 64 KB ボディ検査で試してみた

AWS WAF のマネージドルール PHP2Shell_BODY は、カスタムルール PHP2Shell と同じリクエストを止めました。CloudFront でボディ検査上限を 64 KB にすると、ALB で検査できなかった 8 KB より後ろの文字列も、上限の位置までサイズルールなしで検出しました。
2026.10.23

はじめに

2026年10月21日、AWS が提供する PHP 用のマネージドルールグループ(AWSManagedRulesPHPRuleSet)に PHP2Shell_BODY が追加されました。

https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-changelog.html

先行記事では、AWS の速報 2026-143-AWS に基づくカスタムルール PHP2Shell と block-oversize-body を、ALB に関連付けた AWS WAF で検証しています。

https://dev.classmethod.jp/articles/aws-security-bulletin-php2shell-waf-rules/

この記事では、カスタムルール PHP2Shell とマネージドルール PHP2Shell_BODY が止めるリクエストを比べました。

あわせて CloudFront でボディ検査上限(body inspection size limit)を 64 KB に設定し、文字列を検査するルールの検査がボディのどの位置まで届くかを測定した結果を紹介します。

PHP2Shell_BODY の概要

PHP2Shell_BODY は、CVE-2026-109619 に該当するリクエストを検出するルールです。ルールグループ AWSManagedRulesPHPRuleSet の WCU は 100 で、ルールのラベルは awswaf:managed:aws:php-app:PHP2Shell_Body です。検出の条件(文字列、メソッド、Content-Type)はドキュメントに書かれていません。

https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-use-case.html

2026年10月23日のコンソールでは、デフォルトのバージョンが 2.5 です。検証は 2.4 に固定して行いました。

AWS WAF コンソールの AWS-AWSManagedRulesPHPRuleSet の画面。バージョンは「デフォルト (Version_2.5 を使用)」、キャパシティは 100 で、6 ルールのアクションはすべて Block

バージョンの確認

速報では、デフォルトのバージョンを使う WebACL はルールグループの更新で自動的に保護され、バージョンを固定している WebACL は最新のバージョンへ更新する必要があると案内されています。PHP2Shell_BODY は Version_2.3 以降に、PHP2Shell_BODY_Extended は Version_2.4 以降に含まれます。

https://aws.amazon.com/security/security-bulletins/2026-143-aws/

次の表は、2026-10-23 13:47 に us-east-1 で取得したバージョン一覧です。

バージョン 公開日時(JST、CLOUDFRONT スコープ) changelog の日付 PHP2Shell_BODY PHP2Shell_BODY_Extended 変更内容(changelog)
Version_2.5(現在のデフォルト) 2026-10-23 09:25 2026-10-22 あり あり PHP2Shell_BODY_Extended の検出シグネチャを改善(CVE-2026-109618、CVE-2026-109619)
Version_2.4 2026-10-22 19:39 2026-10-22 あり 追加 PHP2Shell_BODY_Extended を追加。CVE-2026-109618 を直接検出し、2.3 の案内(CRS の SizeRestrictions_BODY)に代わるもの
Version_2.3 2026-10-22 09:29 2026-10-21 追加 なし PHP2Shell_BODY を追加(CVE-2026-109619)。CVE-2026-109618 は CRS の SizeRestrictions_BODY(8 KB 超のボディを Block)での保護を案内
Version_2.2 2026年3月 2026年3月 なし なし 検出の改善、PHPHighRiskMethodsVariables_URIPATH を追加
Version_2.1 2024年7月 2024年7月 なし なし PHPHighRiskMethodsVariables_BODY と _QUERYSTRING に JS_DECODE を追加
Version_2.0 2023年2月 2023年2月 なし なし 全ルールのシグネチャ改善。_QUERYARGUMENTS を _QUERYSTRING に置き換え、_HEADER を追加。ラベル名を変更
Version_1.1 2021年10月 記載なし なし なし changelog に記載なし
Version_1.0 2021年10月 記載なし なし なし changelog に記載なし

使っているバージョンは、コンソールの「バージョン」欄で確認できます。固定している場合は、get-web-acl の応答の Rules[].Statement.ManagedRuleGroupStatement.Version にも含まれます。固定を外してデフォルトのバージョンに追従させる場合は、「バージョン」欄でデフォルトを選びます。

公開されているバージョンは list-available-managed-rule-group-versions の応答の Versions に、デフォルトのバージョンは CurrentDefaultVersion に含まれます。

aws wafv2 list-available-managed-rule-group-versions \
  --name AWSManagedRulesPHPRuleSet \
  --vendor-name AWS \
  --scope CLOUDFRONT \
  --region us-east-1

ALB など REGIONAL の WebACL は、--scope REGIONAL --region <WebACL のリージョン> に変えて実行します。公開日時はスコープごとに異なるため、使っているスコープで確認します。

WebACL への設定と WAF ログ

ルールグループには PHP2Shell_BODY のほか、PHPHighRiskMethodsVariables_* の 4 ルールと CVE-2026-109618 向けの PHP2Shell_BODY_Extended があります。計 6 ルールの既定アクションは、すべて Block です。検証では PHP2Shell_BODY だけを Block にし、ほかの 5 ルールを Count に上書きしました。CloudFormation で WebACL の Rules に追加した要素は次のとおりです。

- Name: AWSManagedRulesPHPRuleSet
  Priority: 10
  OverrideAction:
    None: {}
  Statement:
    ManagedRuleGroupStatement:
      VendorName: AWS
      Name: AWSManagedRulesPHPRuleSet
      Version: Version_2.4
      RuleActionOverrides:
        - Name: PHP2Shell_BODY
          ActionToUse:
            Block: {}
        - Name: PHP2Shell_BODY_Extended
          ActionToUse:
            Count: {}
        - Name: PHPHighRiskMethodsVariables_HEADER
          ActionToUse:
            Count: {}
        - Name: PHPHighRiskMethodsVariables_QUERYSTRING
          ActionToUse:
            Count: {}
        - Name: PHPHighRiskMethodsVariables_BODY
          ActionToUse:
            Count: {}
        - Name: PHPHighRiskMethodsVariables_URIPATH
          ActionToUse:
            Count: {}
  VisibilityConfig:
    CloudWatchMetricsEnabled: true
    SampledRequestsEnabled: true
    MetricName: AWSManagedRulesPHPRuleSet

Version_2.4 は検証で固定した値です。Version を書かない場合はデフォルトのバージョンが使われ、AWS によるルールの更新が自動で反映されます。Version を指定するとそのバージョンに固定され、以降の更新は反映されません。

PHP2Shell_BODY を Count にすると、リクエストを止めずに、一致したことを WAF ログに記録できます。次は、ALB で全ルールを Count にした構成の WAF ログから、該当部分を抜き出したものです。ログの出力先は CloudWatch Logs で、ロググループ名は aws-waf-logs- で始める必要があります。

{
  "action": "ALLOW",
  "terminatingRuleId": "Default_Action",
  "ruleGroupList": [
    {
      "ruleGroupId": "AWS#AWSManagedRulesPHPRuleSet#Version_2.4",
      "nonTerminatingMatchingRules": [
        {
          "ruleId": "PHP2Shell_BODY",
          "action": "COUNT",
          "overriddenAction": "BLOCK",
          "ruleMatchDetails": []
        }
      ]
    }
  ],
  "labels": [
    {
      "name": "awswaf:managed:aws:php-app:PHP2Shell_Body"
    }
  ]
}

PHP2Shell_BODY_Extended は、今回送った無害なダミーリクエストでは ALB・CloudFront のどちらでも一致しませんでした。

カスタムルールとの比較

検証した構成

PHP2Shell_BODY の検出条件は公開されていないため、定義どうしを見比べることはできません。そこで、先行記事のカスタムルール 2 つ(PHP2Shell と block-oversize-body)を Block にした構成と、PHP2Shell_BODY だけを Block にした構成に同じ形のリクエストを送り、実際の動作を比べました。ALB と CloudFront で共通の 55 ケースに加え、CloudFront では検査上限の境界付近とボディサイズ別の 22 ケースを送りました。CloudFront のボディ付き GET の 2 ケースは、CloudFront が WAF の前に 403 を返すため比較に含めていません。

検証した環境は次のとおりです。

  • ALB: 東京リージョン。ボディ検査上限は 8 KB 固定
  • CloudFront: us-east-1 の CLOUDFRONT スコープの WebACL。ボディ検査上限は 64 KB に設定
  • ルールグループ: Version_2.4 に固定
  • 上限 16 KB での PHP2Shell_BODY の測定だけは、PHP2Shell_BODY_Extended も Block にした構成

リクエストは x-case ヘッダで識別しました。止めたルールは、Block のカスタムレスポンスで付けた応答ヘッダ x-waf-blocked-by と WAF ログで確認しました。

送ったのはいずれも無害なダミーです。オリジンは固定応答を返すものを使い、応答のステータスコードで判定しました。

カスタムルール PHP2Shell は、メソッドが POST で、PHPSESSID が Cookie のキーまたはボディにあり、ボディに PHP_SESSION_UPLOAD_PROGRESS があるリクエストに一致します。block-oversize-body は、ボディが閾値より大きいときに一致し、OversizeHandling は MATCH です。

カスタムルール PHP2Shell の定義(CloudFormation の YAML)
- Name: block-php-upload-progress
  Priority: 4
  Action:
    Block: {}
  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
  VisibilityConfig:
    CloudWatchMetricsEnabled: true
    SampledRequestsEnabled: true
    MetricName: block-php-upload-progress

同じリクエストを止めるか

カスタムの列は PHP2Shell と block-oversize-body の 2 ルールを Block にした構成、マネージドの列は PHP2Shell_BODY だけを Block にした構成です。カスタムの block-oversize-body の閾値は、ALB・CloudFront とも 8,192 です。表の値はいずれも 1 回ずつ測定した結果です。

リクエスト ALB カスタム ALB マネージド CloudFront(64 KB)カスタム CloudFront(64 KB)マネージド
POST、Cookie に PHPSESSID、ボディに PHP_SESSION_UPLOAD_PROGRESS 403 PHP2Shell 403 PHP2Shell_BODY 403 PHP2Shell 403 PHP2Shell_BODY
POST、ボディに PHP_SESSION_UPLOAD_PROGRESS だけ 200 200 200 200
POST、JSON のボディに PHPSESSID と PHP_SESSION_UPLOAD_PROGRESS 403 PHP2Shell 403 PHP2Shell_BODY 403 PHP2Shell 403 PHP2Shell_BODY
公開 PoC の並びを無害化して再現した POST(約 1 MB) 403 oversize 200 403 PHP2Shell 403 PHP2Shell_BODY

全ケースで見ると、PHP2Shell_BODY が 403 にしたリクエストの集合は、カスタム PHP2Shell が 403 にした集合と環境ごとに一致しました(ALB 26 件、CloudFront 41 件)。JSON、text/plain、Content-Type なし、urlencoded のボディに PHPSESSID と PHP_SESSION_UPLOAD_PROGRESS の両方があるリクエストは、どちらの構成でも止まりました。メソッドが PUT や PATCH のリクエスト、フィールド名を小文字にしたリクエスト、片方だけを含むリクエストは、どちらの構成でも通りました。

ALB の 8 KB と CloudFront の 64 KB

ボディ検査上限の仕様

ボディ検査上限は、WAF がボディを先頭から何バイトまで検査するかを決める値です。ALB は 8 KB(8,192 バイト)で固定です。CloudFront は既定が 16 KB(16,384 バイト)で、16 KB 刻みで 32 KB、48 KB、64 KB に設定できます。

https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-setting-body-inspection-limit.html

CloudFront で 64 KB まで設定できるようになったのは 2023年4月です。

https://aws.amazon.com/about-aws/whats-new/2023/04/aws-waf-body-inspections-amazon-cloudfront-distributions/

CloudFront では、WebACL の AssociationConfig で DefaultSizeInspectionLimit に KB_16、KB_32、KB_48、KB_64 のいずれかを指定します。

AssociationConfig:
  RequestBody:
    CLOUDFRONT:
      DefaultSizeInspectionLimit: KB_64

既定の 16 KB を超えて検査すると、追加料金がかかります。2026年10月23日時点の単価は、16 KB を超える分の 16 KB ごとに 100 万リクエストあたり 0.30 ドルで、対象はボディが 16 KB を超えるリクエストの検査だけです。

https://aws.amazon.com/waf/pricing/

CloudFront の 64 KB で文字列を検査するルールが止める範囲

先行記事で示した ALB の先頭 8 KB の境界は、PHP2Shell_BODY でも同じでした。8 KB より後ろに PHP_SESSION_UPLOAD_PROGRESS があるリクエストは、PHP2Shell_BODY だけの構成では 200 で通りました。カスタム構成では、block-oversize-body(閾値 8,192)が 403 にしました。公開 PoC の並びもこの形です。1,001 個のダミーフィールドの後ろに PHPSESSID と PHP_SESSION_UPLOAD_PROGRESS の 2 フィールド(以下、予約フィールド)があり、その後ろに大きいフィールドが続きます。予約フィールドは先頭から約 56 KB の位置にあります。再現したのはフィールド名の並びと大きさだけで、PoC は実行していません。

ボディ検査上限を 64 KB にした CloudFront では、この位置に予約フィールドがあるリクエストを、PHP2Shell_BODY とカスタム PHP2Shell がどちらも 403 にしました。

リクエスト PHP2Shell_BODY だけ(サイズルールなし) カスタム PHP2Shell + block-oversize-body(閾値 65,536)
PHP_SESSION_UPLOAD_PROGRESS の終端が 32,000 バイト目(ボディ 33,073 バイト) 403 PHP2Shell_BODY 403 PHP2Shell
公開 PoC の並びから大きいフィールドを除いたもの(ボディ 56,335 バイト) 403 PHP2Shell_BODY 403 PHP2Shell
PHP_SESSION_UPLOAD_PROGRESS の終端が 65,537 バイト目(ボディ 66,610 バイト) 200 403 oversize
正規の POST、20 KB の JSON 200 200
正規の POST、65,536 バイト 200 200
正規の POST、65,537 バイト 200 403 oversize
正規の POST、100 KB の画像アップロード 200 403 oversize

終端が 65,537 バイト目のリクエストは、PHP_SESSION_UPLOAD_PROGRESS が検査上限の外にあるため、文字列を検査するルールでは通りました。閾値 65,536 の構成では、block-oversize-body が止めました。

次の表は、PHP_SESSION_UPLOAD_PROGRESS の終端が先頭から何バイト目までなら文字列を検査するルールが一致したかを、検査上限ごとに示します。カスタム PHP2Shell の列は、PHP2Shell が一致した位置です。

構成 PHP2Shell_BODY が一致した最大の位置(バイト目) カスタム PHP2Shell が一致した最大の位置(バイト目)
ALB(上限 8 KB 固定) 8,192 8,192
CloudFront(上限 16 KB) 16,384 16,384
CloudFront(上限 64 KB) 65,536 65,536

上限 16 KB のまま block-oversize-body の閾値だけを 65,536 にしたカスタム構成では、16,385 バイト以上の POST を block-oversize-body が 403 にしました。OversizeHandling が MATCH の場合、検査上限を超えたボディは閾値にかかわらず一致と判定されるためです。

予約フィールドの位置は、手前に置くダミーフィールドの大きさで決まります。次は PHP_SESSION_UPLOAD_PROGRESS の終端を 32,000 バイト目に置く例です。

# PHP_SESSION_UPLOAD_PROGRESS の終端が N+187 バイト目になる POST(N=31813 で 32,000 バイト目)
# 表のリクエストは、この後ろに約 1,000 バイトのフィールドを追加したもの
mkpart() { printf -- '--x\r\nContent-Disposition: form-data; name="%s"\r\n\r\n%s\r\n' "$1" "$2"; }
fill()   { head -c "$1" /dev/zero | tr '\0' 'a'; }
N=31813
{ mkpart pad "$(fill "$N")"; mkpart PHPSESSID dummy; mkpart PHP_SESSION_UPLOAD_PROGRESS dummy; printf -- '--x--\r\n'; } > f.bin
curl -s -o /dev/null -w '%{http_code}\n' -X POST "https://<ホスト名>/" \
  -H 'Content-Type: multipart/form-data; boundary=x' \
  --data-binary @f.bin

サイズ別の POST は、次のように指定したバイト数のボディを作って送りました。

# 65,536 バイトの POST
head -c 65536 /dev/zero | tr '\0' 'a' > body.bin
curl -s -o /dev/null -w '%{http_code}\n' -X POST "https://<ホスト名>/" \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @body.bin

まとめ

AWS WAF の PHP ルールグループ(AWSManagedRulesPHPRuleSet)に追加された PHP2Shell_BODY は、ALB と CloudFront のどちらでも、先行記事のカスタムルール PHP2Shell と同じリクエストを止めました。

PHP2Shell_BODY はカスタムルールを書くより簡単に導入でき、AWS によるルールの調整も期待できます。調整が反映されるのはデフォルトのバージョンを使う WebACL なので、バージョンを固定している場合は確認してください。

ボディ検査上限は ALB が 8 KB 固定、CloudFront は最大 64 KB(既定 16 KB)です。上限を超えるリクエストを block-oversize-body で Block すれば PHP2Shell のリスクを軽減できると考えられますが、フォームやアップローダーの正規リクエストも遮断するおそれがあります。

Block で導入するときは、WAF ログを記録して、意図しないブロックが起きていないか確認することをおすすめします。また、適切に設定した WAF には、PHP の脆弱性のリスク軽減に一定の効果が期待できますが、完全な対策ではありません。可能な限り速やかに、PHP を修正版(各系列の 8.5.12、8.4.27、8.3.36、8.2.35 以降)へ更新することをおすすめします。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事