概要
開発中のwebサービスにコメント投稿機能があるのですが、コメント内にURLを含むとコメントが出来ないことが分かりました。
調べてみるとAWSのWAFでブロックされていることが分かったので、許可ルールとして登録することでコメントできるように対応しました。
環境
AWSでECSを使ってアプリをデプロイしており、ELBで外部からのアクセスを受けています。
ELBにWAFをアタッチしており、不正アクセスをブロックしているという環境です。
発生事象
コメント内にURLを含むとコメントすると403エラーとなっており、ELBののログを見るとWAFにブロックされていました。
さらにWAFのサンプルリクエスト機能からコメント投稿に関するアクセスを検索してみると、WAFに設定したブロックのルールに該当していました。
対象のルールは Fortinet Managed Rules for AWS WAF - Complete OWASP Top 10を適用したもので、URL付きのコメントをクロスサイトスクリプティングとみなしてブロックしていました。
アプリ側で改修する方法もありますが、一旦WAFで許可することにします。
対応内容
WAFはterraformで管理しているので、terraformで aws_wafv2_regex_pattern_set
と aws_wafv2_rule_group
リソースを新たに作成し、aws_wafv2_web_acl
の中に許可ルールを追加することでコメント投稿のURLからのみ投稿できるようにしました。
- aws_wafv2_regex_pattern_set
コメント用のURLを正規表現で登録します。
resource "aws_wafv2_regex_pattern_set" "this" {
name = aws_wafv2_regex_pattern_set
scope = "REGIONAL"
regular_expression {
regex_string = "foo/bar/ID[A-Z0-9]*/comments" ## コメントのURLを正規表現で登録
}
}
- aws_wafv2_rule_group
aws_wafv2_regex_pattern_set
のURLかつHTTPのメソッドが(POST|PUT|PATCH)
のものを許可するルールグループを作成します。
resource "aws_wafv2_rule_group" "this" {
name = aws_wafv2_rule_group
scope = "REGIONAL"
capacity = 50
rule {
name = "allow_requests"
priority = 4
action {
allow {}
}
statement {
and_statement {
statement {
regex_pattern_set_reference_statement {
arn = aws_wafv2_regex_pattern_set.this.arn
field_to_match {
uri_path {}
}
text_transformation {
priority = 0
type = "NONE"
}
}
}
statement {
or_statement {
statement {
byte_match_statement {
field_to_match {
method {}
}
search_string = "POST"
positional_constraint = "EXACTLY"
text_transformation {
priority = 0
type = "NONE"
}
}
}
statement {
byte_match_statement {
field_to_match {
method {}
}
search_string = "PUT"
positional_constraint = "EXACTLY"
text_transformation {
priority = 0
type = "NONE"
}
}
}
statement {
byte_match_statement {
field_to_match {
method {}
}
search_string = "PATCH"
positional_constraint = "EXACTLY"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "allow_requests"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "allow_requests"
sampled_requests_enabled = true
}
}
- aws_wafv2_web_acl
Fortinetのルールでブロックされていたので、Fortinetの手前のpriorityとしてルールを追加します。
resource "aws_wafv2_web_acl" "this" {
name = aws_wafv2_web_acl
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "AWS-managed_rules_amazon_ip_reputation_list"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesAmazonIpReputationList"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWS-managed_rules_amazon_ip_reputation_list"
sampled_requests_enabled = true
}
}
# 追加ルール
rule {
name = "allow_requests"
priority = 2
override_action {
none {}
}
statement {
rule_group_reference_statement {
arn = aws_wafv2_rule_group.this.arn
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "allow_requests"
sampled_requests_enabled = true
}
}
rule {
name = "Fortinet-all_rules"
priority = 3
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "all_rules"
vendor_name = "Fortinet"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "Fortinet-all_rules"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "WebACL"
sampled_requests_enabled = true
}
}
対応結果
WAFのサンプルリクエスト機能から追加したルールでフィルタすると、コメント投稿のアクションがALLOW
となっていることが確認できました。
参考