こんにちは、インフラエンジニアの綿引です。
前回に引き続き、今回も 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 ダッシュボードのルールも作ってみます。