使用Amazon WAF,可以通过预设和自定义的安全规则来帮助阻止恶意流量,从而保护您的应用程序免受常见的网络漏洞和攻击尝试,包括 SQL 注入、跨站脚本 (XSS) 攻击、跨站请求伪造 (CSRF)、文件包含等。对Amazon WAF的日志进行采集和分析,对于优化WAF规则、响应安全事件以及对应用进行进一步加固而言,是一种最佳实践。但是对于Amazon WAF日志的采集、存储、分析都会产生后续的成本,比如S3存储的成本,Athena的查询成本,OpenSearch集群的成本等。在实际的业务场景中,有时候某些特定的高频Web访问本身就产生很大流量,产生大量的Amazon WAF日志,比如健康检查和测试的Web请求,如果能对这些分析中不需要的日志加以过滤,可以节省大量日志采集、存储以及分析产生的成本。
目前Amazon WAF的日志过滤功能支持两种类型的过滤规则,一种是基于Rule action的规则,即从Allow, Block, Count, CAPTCHA和Challenge几种action中选择或排除特定action的日志,显然这种过滤依然比较粗,无法进行更细粒度的日志选择。另一种过滤方式是基于label的过滤,但这种过滤方式只能选择特定的日志标签,无法实现更复杂的过滤逻辑,比如基于网址、访问路径、来源地址的日志过滤。
在Amazon WAF的使用事件中,笔者摸索出了一种可以实现更精细的Amazon WAF日志过滤规则的方法,这里供大家参考。
直接上示例,这里简便起见以terraform模板的形式说明,也可以遵循同样的逻辑通过其他形式配置。
基本的思路是创建一个专门用于过滤日志的Web ACL规则,规则的action设置为count,仅用于打标签。
以下代码创建了一个自定义web规则,为来自于CN,访问/testuri路径的访问打上“demo:ignorelog"的标签
```
resource "aws_wafv2_web_acl" "demo_web_acl" {
name = "demoWebACL"
scope = "REGIONAL"
description = "Tag requests that do not need to be sent to logs"
default_action {
allow {}
}
rule {
name = "CombinedConditionsForIgnoreLog"
priority = 1
action {
count {}
}
statement {
or_statement {
statement {
and_statement {
statement {
geo_match_statement {
country_codes = ["CN"]
}
}
statement {
byte_match_statement {
field_to_match {
uri_path {}
}
positional_constraint = "EXACTLY"
search_string = "/testuri"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
statement {
byte_match_statement {
field_to_match {
single_header {
name = "User-Agent"
}
}
positional_constraint = "CONTAINS"
search_string = "demo.app"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
rule_label {
name = "demo:ignorelog"
}
visibility_config {
cloudwatch_metrics_enabled = false
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = false
sampled_requests_enabled = true
}
}
```
其后的处理就比较直接了,在log过滤规则中指定drop label为"demo:ignorelog"的请求即可:
```
loggingConfiguration = {
logDestinationConfigs = [
"arn:aws-cn:firehose:cn-north-1:xxxxxxxxxxxx:deliverystream/aws-waf-logs-xxxxxx"
]
loggingFilterConfigs = {
defaultBehavior = "DROP",
filters = [
{
behavior = "DROP"
conditions = [
{
actionCondition = null
labelNameCondition = "demo:ignorelog"
},
]
requirement = "MEETS_ALL"
},
{
behavior = "KEEP",
...此处省略...
}
]
}
redactedFields = []
},
```
这样就实现了Amazon WAF日志的复杂逻辑细粒度过滤。label是Amazon WAF一个非常重要的功能特性,类似的基于label,还可以实现很多复杂的WAF处理逻辑,比如将Managed rulegroup与自定义的rulegroup相结合,实现类似于“仅对agent为demo.app的访问请求进行SQL注入检查”的逻辑,这里就不再展开。使用Amazon WAF,可以通过预置和可定制的安全规则来帮助阻止恶意流量,从而保护您的应用程序免受常见的网络漏洞和攻击尝试,包括 SQL 注入、跨站脚本 (XSS) 攻击、跨站请求伪造 (CSRF)、文件包含等。对Amazon WAF的日志进行采集和分析,是优化WAF规则,响应安全事件,对应用进行进一步加固的最佳实践。但是对于Amazon WAF日志的采集、存储、分析都会产生后续的成本,比如S3存储的成本,Athena的查询成本,OpenSearch集群的成本等。在实际的业务场景中,有时候某些特定的高频Web访问本身就产生很大流量,产生大量的Amazon WAF日志,比如健康检查和测试的Web请求,如果能对这些分析中不需要的日志加以过滤,可以节省大量日志采集、存储以及分析产生的成本。
目前Amazon WAF的日志过滤功能支持两种类型的过滤规则,一种是基于Rule action的规则,即从Allow, Block, Count, CAPTCHA和Challenge几种action中选择或排除特定action的日志,显然这种过滤依然比较粗,无法进行更细粒度的日志选择。另一种过滤方式是基于label的过滤,但这种过滤方式只能选择特定的日志标签,无法实现更复杂的过滤逻辑,比如基于网址、访问路径、来源地址的日志过滤。
在Amazon WAF的使用事件中,笔者摸索出了一种可以实现更精细的Amazon WAF日志过滤规则的方法,这里供大家参考。
直接上示例,这里简便起见以terraform模板的形式说明,也可以遵循同样的逻辑通过其他形式配置。
基本的思路是创建一个专门用于过滤日志的Web ACL规则,规则的action设置为count,仅用于打标签。
以下代码创建了一个自定义web规则,为来自于CN,访问/testuri路径的访问打上“demo:ignorelog"的标签
```
resource "aws_wafv2_web_acl" "demo_web_acl" {
name = "demoWebACL"
scope = "REGIONAL"
description = "Tag requests that do not need to be sent to logs"
default_action {
allow {}
}
rule {
name = "CombinedConditionsForIgnoreLog"
priority = 1
action {
count {}
}
statement {
or_statement {
statement {
and_statement {
statement {
geo_match_statement {
country_codes = ["CN"]
}
}
statement {
byte_match_statement {
field_to_match {
uri_path {}
}
positional_constraint = "EXACTLY"
search_string = "/testuri"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
statement {
byte_match_statement {
field_to_match {
single_header {
name = "User-Agent"
}
}
positional_constraint = "CONTAINS"
search_string = "demo.app"
text_transformation {
priority = 0
type = "NONE"
}
}
}
}
}
rule_label {
name = "demo:ignorelog"
}
visibility_config {
cloudwatch_metrics_enabled = false
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = false
sampled_requests_enabled = true
}
}
```
其后的处理就比较直接了,在log过滤规则中指定drop label为"demo:ignorelog"的请求即可:
```
loggingConfiguration = {
logDestinationConfigs = [
"arn:aws-cn:firehose:cn-north-1:xxxxxxxxxxxx:deliverystream/aws-waf-logs-xxxxxx"
]
loggingFilterConfigs = {
defaultBehavior = "DROP",
filters = [
{
behavior = "DROP"
conditions = [
{
actionCondition = null
labelNameCondition = "demo:ignorelog"
},
]
requirement = "MEETS_ALL"
},
{
behavior = "KEEP",
...此处省略...
}
]
}
redactedFields = []
},
```
这样就实现了Amazon WAF日志的复杂逻辑细粒度过滤。label是Amazon WAF一个非常重要的功能特性,类似的基于label,还可以实现很多复杂的WAF处理逻辑,比如将Managed rulegroup与自定义的rulegroup相结合,实现类似于“仅对agent为demo.app的访问请求进行SQL注入检查”的逻辑,这里就不再展开。