はじめに
CloudformationにてAWS WAFを構築した際にマネージドルールの例外条件を設定する機会がありまして、せっかくなので記事に残そうと思い執筆します。
普段はNoUserAgent_Headerの通信はAWS WAFにて遮断するも、特定のURIを持つ通信だけは例外的に通信を許可するという設定を行う必要性があり、こちらの例外処理をCloudformationにて作成しました。
目次
- WAFとは
- WAFのマネージドルール
- 例外処理の設定
- Cloudformationにて記載
- 参考資料
AWS WAFとは
まずは、AWS WAFとは何かを記載するところからはじめます。AWS WAFとは、AWSが提供しているクラウド型のWebアプリケーションファイアウォールサービスです。Webアプリケーションに対する様々な攻撃を検知し、防御するためのサービスとなります。ALBやCloudFrontなどに紐づけてインターネットからの通信で不正な検知し遮断します。
WAFのマネージドルール
AWS WAFではルールを設定し遮断します。自分でカスタマイズすることもできますが、AWSが提供するマネージドルールを利用することもできます。マネージドルールとは、AWSが定期的に更新する、一般的なWeb攻撃に対するルールの集合です。マネージドルールを利用することで、WAFのルールの作成や管理の手間を省くことができます。例えば、マネージドルールには、以下のような種類があります。
- AWSManagedRulesCommonRuleSet: 一般的なWeb攻撃に対する基本的なルールセット
- AWSManagedRulesAmazonIpReputationList: AWSが管理するIPリピュテーションリストに基づいて、不正なアクセスをブロックするルールセット
- AWSManagedRulesKnownBadInputsRuleSet: SQLインジェクションやクロスサイトスクリプティングなどの既知の悪意のある入力をブロックするルールセット
- AWSManagedRulesAnonymousIpList: 匿名化されたIPアドレスからのアクセスをブロックするルールセット
- AWSManagedRulesBotControlRuleSet: ボットやスクレイピングなどの自動化されたアクセスをブロックするルールセット
このようなルールセットの中に複数のルールがあり、それぞれのルールを元に通信の検知を行っています。
例外処理の設定
マネージドルールを利用する場合でも、特定の条件下でルールをカスタマイズでき例外処理を設定できます。今回は、AWSManagedRulesCommonRuleSetのうち、NoUserAgent_HEADERというHTTPリクエストのヘッダ「User-Agent」の項目が設定されていない場合にアクセスを遮断するルールにて例外条件を設定します。
User-Agentという項目は、リクエストを送信したブラウザやアプリケーションの種類やバージョンなどを識別するために使われており、User-Agentがないリクエストは、不正なアクセスや攻撃の可能性が高いと考えられるため、NoUserAgent_HEADERというルールでブロックされます。
ただし、特定のプログラム処理において、意図的にUser-Agentがないリクエストを送信する仕組みがある場合、その通信も誤って誤検知しWAFが遮断することもあり、例外処理を設定する必要があります。
具体的に例外処理を行うときの仕組みは以下の通りです。
- 例外条件を適用したいルールについてはWAFでの検知時のアクションをBLOCKからCOUNTへ変更
- COUNTモードのルールで検知された通信は、遮断しないが検知されたことを表す「ラベル」が付与
- 今回のラベルは
awswaf:managed:aws:core-rule-set:NoUserAgent_Header
となる
- 今回のラベルは
- COUNTモードのラベルが付与された通信に対して、別途カスタムルールを作成し以下のように条件を設定
- 条件1: ラベル
awswaf:managed:aws:core-rule-set:NoUserAgent_Header
が付与されている - 条件2: 対象URIパスが/hogehoge/で始まるもの以外 (NOT条件)
- 条件1: ラベル
この設定によって、以下のように振る舞いが変わります。
- 対象URIパスが/hogehoge/で始まるもの → ブロックされない
- 対象URIパスが/hogehoge/で始まるもの以外 → ブロックされる
図で表すと以下の様になります。
Cloudformationにて記載
ここから例外処理の内容をCloudformationにて記述していきます。
まずは、マネージドルールについて抜粋して記述していきます。
Statementを記載する際、ExcludedRules
にてNoUserAgent_HEADER
を指定します。
この記述でNoUserAgent_HEADERのルールがOverride to COUNTとなりカウントモードに変更されます。
# Web ACL ルール設定
Rules:
# AWSマネージドルール(ウェブアプリケーションにとっての一般的な脅威をブロック)
- Name: AWS-AWSManagedRulesCommonRuleSet
Priority: 1
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
# NoUserAgent_HEADERをカウントモードへ変更
ExcludedRules:
- Name: NoUserAgent_HEADER
OverrideAction:
None: {}
VisibilityConfig:
CloudWatchMetricsEnabled: true
SampledRequestsEnabled: true
MetricName: AWS-AWSManagedRulesCommonRuleSet
次にCOUNTモードのラベルが付与された通信に対して、別途カスタムルールを作成します。
AndStatement
で2つの条件を組み合わせたルールを作成します。
LabelMatchStatement
の条件にてScopeをLABELに設定し、awswaf:managed:aws:core-rule-set:NoUserAgent_Header
のラベルを持つ通信を検知するようにします。
NotStatementの条件にてラベルが付与されている通信のうち、/hogehoge/
の通信を持たない通信はAction Blockで遮断するようにします。
ActionをBlockにしたことによって、対象URIパスが/hogehoge/で始まるもの以外はブロックされる仕組みになります。
Rules:
# カスタムルール(NoUserAgent_HEADERの通信のうち、/hogehoge/hoge.pyのURIを持つもののみアクセス許可)
# NoUserAgent_Headerのラベルを持つ通信のうち、/hogehoge/hoge.pyのURI以外を全てブロックする
- Name: NoUserAgentHeaderCustomeRule
Priority: 2
Statement:
AndStatement:
Statements:
# awswaf:managed:aws:core-rule-set:NoUserAgent_Headerのラベルを持つ通信を検知する条件
- LabelMatchStatement:
Scope: LABEL
Key: awswaf:managed:aws:core-rule-set:NoUserAgent_Header
# ラベルを持つ通信のうち/hogehoge/のURIを持たないものを検知する条件
- NotStatement:
Statement:
ByteMatchStatement:
SearchString: /hogehoge/
FieldToMatch:
UriPath: {}
TextTransformations:
- Priority: 0
Type: NONE
PositionalConstraint: STARTS_WITH
最後にAWS WAFに関するCloudformationの全体像を記述します。
なお、今回は例外処理を記載するための最低限の記述となりまして、この内容でセキュリティが担保されるものではないことをご了承ください。
# ------------------------------------------------------------#
# WAF (Web ACL) 作成
#
# ------------------------------------------------------------#
AWSTemplateFormatVersion: "2010-09-09"
Description: Waf Rule Create.
Resources:
# WAF (Web ACL)を作成
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: custome-waf
Scope: REGIONAL
DefaultAction:
Allow: {}
VisibilityConfig:
CloudWatchMetricsEnabled: true
SampledRequestsEnabled: true
MetricName: !Sub custome-waf
# Web ACL ルール設定
Rules:
# AWSマネージドルール(ウェブアプリケーションにとっての一般的な脅威をブロック)
- Name: AWS-AWSManagedRulesCommonRuleSet
Priority: 1
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
# NoUserAgent_HEADERをカウントモードへ変更
ExcludedRules:
- Name: NoUserAgent_HEADER
OverrideAction:
None: {}
VisibilityConfig:
CloudWatchMetricsEnabled: true
SampledRequestsEnabled: true
MetricName: AWS-AWSManagedRulesCommonRuleSet
# カスタムルール(NoUserAgent_HEADERの通信のうち、/hogehoge/のURIを持つもののみアクセス許可)
# NoUserAgent_Headerのラベルを持つ通信のうち、/hogehoge/のURI以外を全てブロックする
- Name: NoUserAgentHeaderCustomeRule
Priority: 2
Statement:
AndStatement:
Statements:
# awswaf:managed:aws:core-rule-set:NoUserAgent_Headerのラベルを持つ通信を検知する条件
- LabelMatchStatement:
Scope: LABEL
Key: awswaf:managed:aws:core-rule-set:NoUserAgent_Header
# ラベルを持つ通信のうち/hogehoge/のURIを持たないものを検知する条件
- NotStatement:
Statement:
ByteMatchStatement:
SearchString: /hogehoge/
FieldToMatch:
UriPath: {}
TextTransformations:
- Priority: 0
Type: NONE
PositionalConstraint: STARTS_WITH
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: NoUserAgentHeaderCustomeRule
参考資料
今回の例外処理の設定、Cloudformationを記載するにあたり以下の記事が大変参考になりました。
ありがとうございました。
[AWS WAF] マネージドルールグループに対して例外条件を設定する