AWS WAFの新機能「プレパーステキスト変換」を CLIで試してみた
はじめに
2026年7月29日のアップデートで、AWS WAFでプレパーステキスト変換(pre-parse text transformations)が利用できるようになりました。
プレパーステキスト変換は、クエリ文字列をキーバリューペアへパースする前に正規化を挟む機能です。従来のテキスト変換は、クエリ引数を検査するときはパース後の値に働きます。そのため、区切り文字の扱いをパース結果へ反映できません。公式ドキュメントでは、プレパーステキスト変換を適用できるのはSingleQueryArgumentまたはAllQueryArgumentsを検査するステートメントだと説明されています。
変換なしのルールでは、セミコロン区切り・URLエンコード済みセミコロン区切りのどちらも一致しませんでした。プレパーステキスト変換を設定した結果は、次のとおりです。
| クエリの区切り | 適用したプレパーステキスト変換(Type) |
|---|---|
| セミコロン区切り | REPLACE_SEMICOLONS_WITH_AMPERSANDS |
| URLエンコード済みセミコロン区切り | URL_DECODE → REPLACE_SEMICOLONS_WITH_AMPERSANDS |
検証内容
Countアクションとルールラベルを設定する
検証環境は次のとおりです。
| 項目 | 値 |
|---|---|
| AWS CLI | 2.36.11 |
| リージョン | ap-northeast-1 |
| Web ACL スコープ | REGIONAL |
| バックエンド | 固定応答 ALB |
| ログ出力先 | CloudWatch Logs |
ブロックアクションによって後続ルールの評価が中断しないよう、検証用ルールはCountアクションとし、各ルールに検証用のWAFラベルを付与しました。WAFログのレコードとHTTPリクエストは、クエリ文字列をキーにして対応付けました。Countはリクエストをブロックしないため、判定根拠はHTTPステータスではなくlabelsとnonTerminatingMatchingRulesとしました。テスト用のWeb ACLにはブロックするルールを置かず、この検証用のCountルールだけを設定しました。
# LockToken を取得
LOCK_TOKEN=$(aws wafv2 get-web-acl \
--name preparse-test-webacl \
--id 11111111-2222-3333-4444-55555555aaaa \
--scope REGIONAL \
--region ap-northeast-1 \
--query LockToken --output text)
# Count ルールとラベルを設定
aws wafv2 update-web-acl \
--name preparse-test-webacl \
--id 11111111-2222-3333-4444-55555555aaaa \
--scope REGIONAL \
--default-action '{"Allow":{}}' \
--lock-token "$LOCK_TOKEN" \
--region ap-northeast-1 \
--visibility-config 'SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=preparse-test-webacl' \
--rules file://rules.json
# 保存された設定を確認
aws wafv2 get-web-acl \
--name preparse-test-webacl \
--id 11111111-2222-3333-4444-55555555aaaa \
--scope REGIONAL \
--region ap-northeast-1
比較のため、同じ照合条件でプレパース変換を持たないコントロールルール(ControlNoPreparsePlain、ControlNoPreparseEncoded)も2本追加しました。--rulesに渡したルール設定から、プレパース変換ありの2本を抜粋します。
[
{
"Name": "PreparseSemicolon",
"Priority": 2,
"Statement": {
"ByteMatchStatement": {
"SearchString": "cHJlcGFyc2UtcGxhaW4=",
"FieldToMatch": { "SingleQueryArgument": { "Name": "target_plain" } },
"TextTransformations": [ { "Priority": 0, "Type": "NONE" } ],
"PositionalConstraint": "EXACTLY",
"PreParseTextTransformations": [
{ "Priority": 0, "Type": "REPLACE_SEMICOLONS_WITH_AMPERSANDS" }
]
}
},
"Action": { "Count": {} },
"RuleLabels": [ { "Name": "test:preparse-semicolon" } ]
},
{
"Name": "PreparseUrlDecodeSemicolon",
"Priority": 4,
"Statement": {
"ByteMatchStatement": {
"SearchString": "cHJlcGFyc2UtZW5jb2RlZA==",
"FieldToMatch": { "SingleQueryArgument": { "Name": "target_encoded" } },
"TextTransformations": [ { "Priority": 0, "Type": "NONE" } ],
"PositionalConstraint": "EXACTLY",
"PreParseTextTransformations": [
{ "Priority": 0, "Type": "URL_DECODE" },
{ "Priority": 1, "Type": "REPLACE_SEMICOLONS_WITH_AMPERSANDS" }
]
}
},
"Action": { "Count": {} },
"RuleLabels": [ { "Name": "test:preparse-url-decode-semicolon" } ]
}
]
SearchStringの値はBase64でエンコードした文字列です。cHJlcGFyc2UtcGxhaW4=はpreparse-plain、cHJlcGFyc2UtZW5jb2RlZA==はpreparse-encodedにあたります。抜粋では各ルールのVisibilityConfigを省いています。更新後のget-web-aclでは、PreParseTextTransformationsとRuleLabelsが保存されていることを確認しました。
セミコロン区切りのクエリを確認する
REPLACE_SEMICOLONS_WITH_AMPERSANDSを設定したルールを対象に、セミコロン区切りとアンパサンド区切りのリクエストを送りました。
| ケース | リクエストのクエリ | HTTP結果 | WAFログで確認したラベル | 非終端一致ルール |
|---|---|---|---|---|
| セミコロン区切り | q=safe;target_plain=preparse-plain |
200 / ALLOW | test:preparse-semicolon |
PreparseSemicolon |
| 通常のアンパサンド区切り(plain) | q=safe&target_plain=preparse-plain |
200 / ALLOW | test:control-no-preparse-plain、test:preparse-semicolon |
ControlNoPreparsePlain、PreparseSemicolon |
セミコロン区切りで一致したのはプレパース変換ありのルールだけで、コントロールルールのラベルは付与されませんでした。アンパサンド区切りでは両方が一致しており、変換の有無が結果を分けたことがラベルから読み取れます。
セミコロン区切りのリクエストに対応するWAFログの抜粋です。labelsの値にはWeb ACL名を含むプレフィックスが付きます。
{
"action": "ALLOW",
"terminatingRuleId": "Default_Action",
"nonTerminatingMatchingRules": [
{ "ruleId": "PreparseSemicolon", "action": "COUNT", "ruleMatchDetails": [] }
],
"httpRequest": { "args": "q=safe;target_plain=preparse-plain" },
"labels": [
{ "name": "awswaf:123456789012:webacl:preparse-test-webacl:test:preparse-semicolon" }
]
}
URLエンコード済みセミコロンを確認する
URL_DECODEとREPLACE_SEMICOLONS_WITH_AMPERSANDSを連鎖させたルールを対象に、次の2ケースのリクエストを送りました。
| ケース | リクエストのクエリ | HTTP結果 | WAFログで確認したラベル | 非終端一致ルール |
|---|---|---|---|---|
| URLエンコード済みセミコロン区切り | q=safe%3Btarget_encoded=preparse-encoded |
200 / ALLOW | test:preparse-url-decode-semicolon |
PreparseUrlDecodeSemicolon |
| 通常のアンパサンド区切り(encoded) | q=safe&target_encoded=preparse-encoded |
200 / ALLOW | test:control-no-preparse-encoded、test:preparse-url-decode-semicolon |
ControlNoPreparseEncoded、PreparseUrlDecodeSemicolon |
URLエンコード済みのセミコロンを含むリクエストでは、デコードと置換を連鎖させたルールだけが一致し、コントロールルールのラベルは付与されませんでした。アンパサンド区切りでは両方のルールが一致しました。
まとめ
クエリ文字列の区切りやエンコードの違いに対応するため、正規表現や複数のルールを組み合わせている場合、今回追加されたプレパーステキスト変換を使うことで、よりシンプルに管理できる可能性があります。プレパーステキスト変換は1つごとに10 WCUを追加しますが、ウェブACLの合計が既定割り当ての1,500 WCU以下であれば、追加料金なしで利用できます。







