こんにちは、インフラエンジニアの綿引です。

前回に引き続き、今回も AWS CloudFormation について記載したいと思います。

今回は「WAF のルール」を作成しようと思いますが、最初に以下ご注意ください。

 

  • Web ACLs や Conditions の作成ではなく Rules の作成である
  • AWS WAF v2 ではなく AWS WAF Classic の設定である

 

対象の方は以下のような方でしょうか。

 

  • CloudFormation 初心者の方
  • WAF のルールを手動で作りたくない

 

テンプレートファイル作成

では早速テンプレートファイルを作成していきます。

今回は以下のテンプレートを作成していくのですが、「Global (CloudFront)」と「Regional WAF Resource」でテンプレートが異なりますのでご注意ください。

CloudFront に設定したかったら Global 用のテンプレートで、ALB などにつけたい場合は Regional 側のテンプレートですね。

作成するテンプレートファイル 内容
WAF-generic-detect-sqli-rules-Regional.yaml SQLインジェクション対策用のルールを作成 (Regional)
WAF-generic-detect-sqli-rules.yaml SQLインジェクション対策用のルールを作成 (Global)
WAF-generic-detect-xss-rules-Regional.yaml XSS対策用のルールを作成 (Regional)
WAF-generic-detect-xss-rules.yaml XSS対策用のルールを作成 (Global)
WAF-ip-block-rules-Regional.yaml IP ベースのブロックルールを作成 (Regional)
WAF-ip-block-rules.yaml IP ベースのブロックルールを作成 (Global)
WAF-ua-block-rules-Regional.yaml UserAgent ベースのブロックルールを作成 (Regional)
WAF-ua-block-rules.yaml UserAgent ベースのブロックルールを作成 (Global)

まずは Global と Regional のソースの違いです。

Global と Regional のソースの違い

違いとしては Type が「WAF」か「WAFRegional」かの違いです。

・Global 用

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  SqlInjDetection:
    Type: "AWS::WAF::SqlInjectionMatchSet"

・Regional 用

Resources:
  SqlInjDetection:
    Type: "AWS::WAFRegional::SqlInjectionMatchSet"  # ここの真ん中が異なる

テンプレート内の後の記載は一緒なので、以下には「Global」側のみ記載いたします。

SQLインジェクション対策用のルールを作成

設定内容としては以下です。

 

  • ルール名は「generic-detect-sqli」
  • Filter の設定は Header cookie・Query string・URI に HTML decode と URI decode
  • SqlInjDetection の部分で「conditions」を作成し、SqlInjRule で「ルール」を作成
  • ルール作成の DataId の部分で、上部で定義した「conditions」を指定

 

ソースは以下になります。

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  SqlInjDetection:
    Type: "AWS::WAF::SqlInjectionMatchSet"
    Properties:
      Name: "generic-detect-sqli"
      SqlInjectionMatchTuples:
          - FieldToMatch:
              Type: URI
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: URI
            TextTransformation: HTML_ENTITY_DECODE
          - FieldToMatch:
              Type: QUERY_STRING
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: QUERY_STRING
            TextTransformation: HTML_ENTITY_DECODE
          - FieldToMatch:
              Type: HEADER
              Data: cookie
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: HEADER
              Data: cookie
            TextTransformation: HTML_ENTITY_DECODE
  SqlInjRule:
    Type: "AWS::WAF::Rule"
    Properties:
      Name: "generic-detect-sqli-rules"
      MetricName: "SqlInjRule"
      Predicates:
        -
          DataId:
            Ref: "SqlInjDetection"
          Negated: false
          Type: "SqlInjectionMatch"

XSS対策用のルールを作成

こちらはSQLインジェクション対策用のルールとほぼ同様なので、ソースだけ以下に記載します。

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  DetectXSS:
    Type: "AWS::WAF::XssMatchSet"
    Properties:
      Name: "generic-detect-xss"
      XssMatchTuples:
          - FieldToMatch:
              Type: URI
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: URI
            TextTransformation: HTML_ENTITY_DECODE
          - FieldToMatch:
              Type: QUERY_STRING
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: QUERY_STRING
            TextTransformation: HTML_ENTITY_DECODE
          - FieldToMatch:
              Type: HEADER
              Data: cookie
            TextTransformation: URL_DECODE
          - FieldToMatch:
              Type: HEADER
              Data: cookie
            TextTransformation: HTML_ENTITY_DECODE
  XSSRule:
    Type: "AWS::WAF::Rule"
    Properties:
      Name: "generic-detect-xss-rules"
      MetricName: "XSSRule"
      Predicates:
        -
          DataId:
            Ref: "DetectXSS"
          Negated: false
          Type: "XssMatch"

IP ベースのブロックルールを作成

こちら「Properties」の項目は少し異なりますが形式はほぼ同じです。「Value」部分にブロックしたい IP を記載しています。

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  MyIPSetBlacklist:
    Type: "AWS::WAF::IPSet"
    Properties:
      Name: "ip-block-list"
      IPSetDescriptors:
        -
          Type: "IPV4"
          Value: "XXX.XXX.XXX.XXX/32"  # 拒否したい IP を記載
        -
          Type: "IPV4"
          Value: "XXX.XXX.XXX.XXX/32"  # 拒否したい IP を記載
  MyIPSetRule:
    Type: "AWS::WAF::Rule"
    Properties:
      Name: "ip-block-rules"
      MetricName: "MyIPSetRule"
      Predicates:
        -
          DataId:
            Ref: "MyIPSetBlacklist"
          Negated: false
          Type: "IPMatch"

UserAgent ベースのブロックルールを作成

こちらもほぼ同様です。「TargetString」部分にブロックしたい文字列を記載しています。

今回は例として IE6 を拒否するような形で書いておりますが、「TargetString」の部分を変更いただければご指定の文字列で拒否できるようになります。
(その際 Name なども設定内容に合うよう変更すると良いかと思います。)

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  BlockStringSetUAIE6:
    Type: "AWS::WAF::ByteMatchSet"
    Properties:
      Name: "restrict-user-agent-IE6"
      ByteMatchTuples:
        -
          FieldToMatch:
            Type: "HEADER"
            Data: "User-Agent"
          TargetString: "Mozilla/4.0 (compatible; MSIE 6.0;"
          TextTransformation: "NONE"
          PositionalConstraint: "CONTAINS"
  BlockStringRules:
    Type: "AWS::WAF::Rule"
    Properties:
      Name: "ua-block-rules"
      MetricName: "BlockStringRules"
      Predicates:
        -
          DataId:
            Ref: "BlockStringSetUAIE6"
          Negated: false
          Type: "ByteMatch"

実際のソース

ソースは以下 GitHub に上げておきましたので宜しければお使いください。

GitHub : CloudFormation-Templates WAF

※ 随時更新しているため上記記載の内容とは若干異なる場合があります

 

最後に

今回は CloudFormation を使って WAF のルールを作成しました。

WebACL の作成でも良かったのですが、ルールの方が使いやすいかなと思い、今回はルール作成にしております。

もちろん conditions だけの作成もできるので、ご自身の環境に応じてカスタマイズいただければと思います。

次は CloudWatch ダッシュボードのルールも作ってみます。

Join Us !

ウエディングパークでは、一緒に働く仲間を募集しています!
ご興味ある方は、お気軽にお問合せください(カジュアル面談から可)

採用情報を見る