AWS WAFで正規表現を使って大文字と小文字のパターンがあるパスを除外するルールを設定してみた

2024.06.05

こんにちは、岩城です。

ある事情で以下のような同じようなパスに見えて大文字と小文字のパターンがあるパスに対して、AWS WAF v2のAWSManagedRulesCommonRuleSetでBlockされるリクエストを除外するルールを設定する機会がありました。

  • /devio/PathA/sample.html
  • /devio/patha/sample.html

せっかくなので方法を共有したいと思います。

検証環境の構成

本エントリを執筆するため、検証用に構築した環境は以下のとおりです。

検証環境の前提は、AWS WAF v2でAWSManagedRulesCommonRuleSetをBlockで運用していたところ、CrossSiteScripting_BODYでブロックされてしまった、ということにします。

すべてのリクエストでCrossSiteScripting_BODYを除外させるのではなく、あるパスが含まれるリクエストだけ、CrossSiteScripting_BODYでブロックされないようにしたいです。

このあるパスが、上述の同じのように見えて大文字・小文字のパターンがあるパスです。

WAFのルールは、AWSや3rd Patryが管理するマネージドルールや自身で作成管理するルールの2つがあります。

自身で作成管理するルールにも2つタイプがあり、Regular ruleとRate-based ruleがあります。

本エントリで扱うタイプはRegular ruleであり、Regular ruleはStatementとActionで構成されます。

以下のエントリのようにパスごとに複数Statementを使って設定しても良いのですが、Statementは最大5つまでしか設定できない仕様があります。

除外するパスが多くなるとStatementの設定上限に達してしまうので、極力Statementの数を抑えて設定したいと思います。

これに対して考えられるアプローチは次の2つです。

  • 正規表現パターンセット(Regex pattern sets)を使う
  • 正規表現(Regular expression)を使う

前者は複数の正規表現を列挙してパターンセットに登録できるので、正規表現を変えながら複数のパスに対応させつつ、Statement1つで除外ルールを設定することができます。

後者は単一の正規表現を設定するパターンです。

本エントリを執筆するに至ったケースでは、複数の正規表現を必要としなかったので、後者の正規表現(Regular expression)を使い、大文字・小文字関係なく1つのStatementで除外ルールを設定することにしました。

やってみた

検証環境では、以下のようなWAFのルールを設定しています。

AWSManagedRulesCommonRuleSet

AWSManagedRulesCommonRuleSetは、その名のとおりAWSで管理されているルールセットであり、様々なルールが定義されています。

ここで、CrossSiteScripting_BODYをデフォルトでBlockに設定されていますが、Override to Countに変更します。

CountにするとCrossSiteScripting_BODYで検知したことを示す以下のLabelを付与するだけでBlockされなくなります。

{name=awswaf:managed:aws:core-rule-set:CrossSiteScripting_Body}

このLabelを利用して、後続のExclusion_SizeRestrictions_BODYをトリガーさせるので、AWSManagedRulesCommonRuleSetの後にExclusion_SizeRestrictions_BODYを評価させるPriorityで設定します。

Exclusion_SizeRestrictions_BODY

AWS管理ではなく自身で作成管理するルールです。名前は何でも良いです。以下のようなルールを定義しています。

  • Statement1
    • Labelがawswaf:managed:aws:core-rule-set:CrossSiteScripting_Bodyである場合
  • NOT Statement2
    • URI pathに\/(?i:patha)\/が含まれている場合に除外
  • Then
    • Block

AWSManagedRulesCommonRuleSetでCount判定されたリクエストのうち、パスに\/(?i:patha)\/が含まれていなければBlockします。

以上で、パスに大文字・小文字問わずpathaが含まれていればBlockせずに除外することが可能になります。

おわりに

AWS WAF v2のルールで設定できる正規表現は公式ドキュメントに記載があるとおり、PCRE(Perl Compatible Regular Expressions)の構文をサポートします。

私はDebuggexBetaを利用して、狙った正規表現になっているか確認しながら試行錯誤しました。

今回は一つの正規表現パターンで要件を満たすことができましたが、複数のパスに対して複数の正規表現を定義しなければならない場合があります。

Statementは最大5つまでしか設定できないので、上限に達しそうであればRegex pattern setsの使用を検討してみてください。

正規表現パターンセットの作成 - AWS WAF、 AWS Firewall Manager、および AWS Shield Advanced

本エントリがどなたかのお役に立てれば幸いです。