
AWS WAF のマネージドルール PHP2Shell_BODY をカスタムルールと比べ、CloudFront の 64 KB ボディ検査で試してみた
はじめに
2026年10月21日、AWS が提供する PHP 用のマネージドルールグループ(AWSManagedRulesPHPRuleSet)に PHP2Shell_BODY が追加されました。
先行記事では、AWS の速報 2026-143-AWS に基づくカスタムルール PHP2Shell と block-oversize-body を、ALB に関連付けた AWS WAF で検証しています。
この記事では、カスタムルール 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)はドキュメントに書かれていません。
2026年10月23日のコンソールでは、デフォルトのバージョンが 2.5 です。検証は 2.4 に固定して行いました。

バージョンの確認
速報では、デフォルトのバージョンを使う WebACL はルールグループの更新で自動的に保護され、バージョンを固定している WebACL は最新のバージョンへ更新する必要があると案内されています。PHP2Shell_BODY は Version_2.3 以降に、PHP2Shell_BODY_Extended は Version_2.4 以降に含まれます。
次の表は、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 に設定できます。
CloudFront で 64 KB まで設定できるようになったのは 2023年4月です。
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 を超えるリクエストの検査だけです。
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 以降)へ更新することをおすすめします。










