为 Azure Front Door 优化 Azure Web 应用程序防火墙

Microsoft托管的默认 规则集基于 OWASP 核心规则集 ,包括Microsoft威胁智能收集规则。

通常预期必须调整 Web 应用程序防火墙(WAF)规则,以满足使用 WAF 的应用程序或组织的特定需求。 组织通常通过执行以下作之一来实现优化:

  • 定义规则排除项。
  • 创建自定义规则。
  • 禁用可能导致问题或误报的规则。

本文介绍在阻止应通过 WAF 的请求时可以执行的作。

注释

Microsoft托管的规则集不适用于 Azure Front Door 标准 SKU。 有关不同层 SKU 的详细信息,请参阅 层之间的功能比较

阅读 Azure Front Door WAF 概述适用于 Azure Front Door 文档的 WAF 策略 。 此外,启用 WAF 监视和日志记录。 这些文章介绍了 WAF 的工作原理、WAF 规则集的工作原理以及如何访问 WAF 日志。

了解 WAF 日志

WAF 日志的目的是显示 WAF 匹配或阻止的每个请求。 它是匹配或阻止的所有评估请求的集合。 如果你注意到 WAF 会阻止它不应(误报)的请求,则可以执行一些作。

首先,缩小范围并查找特定请求。 可以将 自定义响应消息配置为 包含 trackingReference 字段,以便轻松标识事件并对该特定值执行日志查询。 查看日志以查找请求的特定 URI、时间戳或客户端 IP。 找到相关的日志条目时,可以针对误报执行作。

例如,假设你有合法流量,其中包含要通过 WAF 的字符串 1=1 。 下面是请求的外观:

POST http://afdwafdemosite.azurefd.net/api/Feedbacks HTTP/1.1
Host: afdwafdemosite.azurefd.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 55

UserId=20&captchaId=7&captchaId=15&comment="1=1"&rating=3

如果尝试请求,WAF 会阻止任何参数或字段中包含 1=1 字符串的流量。 此字符串通常与 SQL 注入攻击相关联。 可以查看日志,并查看请求的时间戳以及阻止或匹配的规则。

以下示例演示基于规则匹配生成的日志条目。 可以使用以下 Log Analytics 查询查找在过去 24 小时内被阻止的请求。

AzureDiagnostics
| where Category == 'FrontDoorWebApplicationFirewallLog'
| where TimeGenerated > ago(1d)
| where action_s == 'Block'

requestUri 字段中,可以看到已专门发出 /api/Feedbacks/ 请求。 接下来,在字段中查找规则 ID 942110ruleName 。 了解规则 ID 后,可以转到 OWASP ModSecurity Core 规则集官方存储库 并按该 规则 ID 进行搜索,以查看其代码并确切了解此规则匹配的内容。

然后,通过检查 action 字段,可以看到此规则设置为在匹配时阻止请求。 你可以确认该请求已被 WAF 阻止,因为 policyMode 该请求已设置为 prevention

现在,检查字段中的信息 details 。 此字段是可以查看 matchVariableNamematchVariableValue 信息的位置。 之所以触发此规则,是因为有人在 comment Web 应用的字段中输入1=1

{
    "time": "2020-09-24T16:43:04.5422943Z",
    "resourceId": "/SUBSCRIPTIONS/<Subscription ID>/RESOURCEGROUPS/<Resource Group Name>/PROVIDERS/MICROSOFT.CDN/PROFILES/AFDWAFDEMOSITE",
    "category": "FrontDoorWebApplicationFirewallLog",
    "operationName": "Microsoft.Cdn/Profiles/WebApplicationFirewallLog/Write",
    "properties": {
        "clientIP": "1.1.1.1",
        "clientPort": "53566",
        "socketIP": "1.1.1.1",
        "requestUri": "http://afdwafdemosite.azurefd.net:80/api/Feedbacks/",
        "ruleName": "DefaultRuleSet-1.0-SQLI-942110",
        "policy": "AFDWAFDemoPolicy",
        "action": "Block",
        "host": "afdwafdemosite.azurefd.net",
        "trackingReference": "0mMxsXwAAAABEalekYeI4S55qpi5R7R0/V1NURURHRTA4MTIAZGI4NGQzZDgtNWQ5Ny00ZWRkLTg2ZGYtZDJjNThlMzI2N2I4",
        "policyMode": "prevention",
        "details": {
            "matches": [
                {
                    "matchVariableName": "PostParamValue:comment",
                    "matchVariableValue": "\"1=1\""
                }
            ],
            "msg": "SQL Injection Attack: Common Injection Testing Detected",
            "data": "Matched Data: \"1=1\" found within PostParamValue:comment: \"1=1\""
        }
    }
}

检查访问日志时也有价值,以扩展你对给定 WAF 事件的知识。 接下来,查看作为对上述事件的响应生成的日志。

可以看到这些日志相关,因为 trackingReference 该值相同。 在提供一般见解的各种字段中,例如 userAgentclientIP,请注意 httpStatusCodehttpStatusDetails 字段。 在这里,可以看到客户端收到了 HTTP 403 响应,这确认此请求被拒绝并被阻止。

{
    "time": "2020-09-24T16:43:04.5430764Z",
    "resourceId": "/SUBSCRIPTIONS/<Subscription ID>/RESOURCEGROUPS/<Resource Group Name>/PROVIDERS/MICROSOFT.CDN/PROFILES/AFDWAFDEMOSITE",
    "category": "FrontDoorAccessLog",
    "operationName": "Microsoft.Cdn/Profiles/AccessLog/Write",
    "properties": {
        "trackingReference": "0mMxsXwAAAABEalekYeI4S55qpi5R7R0/V1NURURHRTA4MTIAZGI4NGQzZDgtNWQ5Ny00ZWRkLTg2ZGYtZDJjNThlMzI2N2I4",
        "httpMethod": "POST",
        "httpVersion": "1.1",
        "requestUri": "http://afdwafdemosite.azurefd.net:80/api/Feedbacks/",
        "requestBytes": "2160",
        "responseBytes": "324",
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36",
        "clientIp": "1.1.1.1",
        "socketIp": "1.1.1.1",
        "clientPort": "53566",
        "timeToFirstByte": "0.01",
        "timeTaken": "0.011",
        "securityProtocol": "",
        "routingRuleName": "DemoBERoutingRule",
        "rulesEngineMatchNames": [],
        "backendHostname": "13.88.65.130:3000",
        "isReceivedFromClient": true,
        "httpStatusCode": "403",
        "httpStatusDetails": "403",
        "pop": "WST",
        "cacheStatus": "CONFIG_NOCACHE"
    }
}

解决误报

若要做出有关处理误报的明智决策,请务必熟悉应用程序使用的技术。 例如,假设技术堆栈中没有 SQL Server,并且你收到与这些规则相关的误报。 禁用这些规则不一定会削弱安全性。

利用此信息,并且知道规则 942110 是与示例中的字符串匹配 1=1 的,可以执行一些作来阻止此合法请求:

小窍门

选择允许通过 WAF 的合法请求的方法时,请尝试尽可能窄地进行请求。 例如,最好使用排除列表而不是完全禁用规则。

使用排除列表

使用排除列表的一个好处是,只有选择排除的匹配变量将不再检查该给定请求。 也就是说,可以在满足特定条件时在特定的请求标头、请求 Cookie、查询字符串参数或请求正文 post 参数之间进行选择,而不是排除要检查的整个请求。 通常检查请求的其他未指定变量。

排除项是全局设置。 配置的排除项适用于通过 WAF 传递的所有流量,而不仅仅是特定的 Web 应用或 URI。 例如,如果 1=1 某个 Web 应用的正文中是有效的请求,但对于同一 WAF 策略下的其他人来说,这可能是一个问题。

如果对不同的应用程序使用不同的排除列表是有意义的,请考虑为每个应用程序使用不同的 WAF 策略并将其应用到每个应用程序的前端。

为托管规则配置排除列表时,可以选择排除:

  • 规则集中的所有规则。
  • 规则组中的所有规则。
  • 单个规则。

可以使用 PowerShellAzure CLIREST API、Bicep、Azure 资源管理器模板或 Azure 门户来配置排除列表。

  • 规则级别的排除项: 在规则级别应用排除意味着不会针对该单个规则分析指定的排除项。 该规则仍将由规则集中的所有其他规则进行分析。 这是排除项最精细的级别。 可以使用它根据 WAF 日志中发现的信息微调托管规则集,解决事件问题。
  • 规则组级别的排除项: 在规则组级别应用排除项意味着不会针对该特定规则类型集分析指定的排除项。 例如,选择 SQLI 作为排除的规则组表示任何特定于 SQLI 的规则都不会检查定义的请求排除项。 它仍将由其他组中的规则(如 PHPRFIXSS)进行检查。 当你确定应用程序不容易受到特定类型的攻击时,这种类型的排除可能很有用。 例如,没有任何 SQL 数据库的应用程序可以排除所有 SQLI 规则,而不会损害其安全级别。
  • 规则集级别的排除项: 在规则集级别应用排除项意味着不会根据该规则集中提供的任何安全规则分析指定的排除项。 此排除是全面的,因此请谨慎使用它。

在此示例中,通过将排除应用到单个规则,在最精细的级别执行排除。 你想要排除匹配变量请求正文后包含的 commentargs 名称。 可以在防火墙日志中看到匹配变量详细信息: "matchVariableName": "PostParamValue:comment"。 属性为 comment. 还可以通过其他几种方式找到此属性名称。 有关详细信息,请参阅 “查找请求属性名称”。

显示排除规则的屏幕截图。

显示特定规则的规则排除的屏幕截图。

有时,在某些情况下,特定参数以可能不直观的方式传递到 WAF。 例如,使用 Microsoft Entra ID 进行身份验证时,会传递令牌。 __RequestVerificationToken令牌通常作为请求 Cookie 传入。

在某些情况下,禁用 Cookie 时,此令牌也会作为请求 post 参数传入。 出于此原因,若要解决Microsoft Entra 标记误报问题,必须确保 __RequestVerificationToken 同时添加到排除列表 RequestCookieNamesRequestBodyPostArgsNames

字段名称(选择器)上的排除项意味着 WAF 将不再计算该值。 字段名称本身将继续评估,在极少数情况下,它可能与 WAF 规则匹配并触发作。

显示规则集的规则排除的屏幕截图。

更改 WAF作

处理 WAF 规则行为的另一种方法是在请求与规则条件匹配时选择它执行的作。 可采取的操作包括允许、阻止、记录和重定向

在此示例中,默认作 已更改为规则 942110 上的 日志 作。 此作会导致 WAF 记录请求,并继续根据剩余较低的优先级规则评估相同的请求。

显示 WAF作的屏幕截图。

执行相同的请求后,可以引用日志,并看到此请求与规则 ID 942110 匹配。 该 action_s 字段现在指示 “日志 ”而不是 “阻止”。 然后展开日志查询以 trackingReference_s 包含信息,以查看此请求的其他情况。

显示显示多个规则匹配项的日志的屏幕截图。

现在,可以看到一个不同的 SQLI 规则匹配,该匹配在处理规则 ID 942110 后发生毫秒。 规则 ID 942310 上匹配的相同请求,这次触发了默认作

在 WAF 优化或故障排除期间使用 日志 作的另一个优点是,可以确定特定规则组中的多个规则是否匹配并阻止给定的请求。 然后,可以在适当的级别(即规则或规则组级别)创建排除项。

使用自定义规则

确定导致 WAF 规则匹配的原因后,可以使用自定义规则来调整 WAF 响应事件的方式。 在托管规则之前处理自定义规则。 它们可以包含多个条件,其作可以是 “允许”、“拒绝”、“日志”或“重定向”。

警告

当请求与自定义规则匹配时,WAF 引擎将停止处理请求。 不会为此请求处理托管规则,其他优先级较低的自定义规则也不会处理。

以下示例显示了一个具有两个条件的自定义规则。 第一个条件查找 comment 请求正文中的值。 第二个条件查找 /api/Feedbacks/ 请求 URI 中的值。

通过使用自定义规则,可以最精细,以便微调 WAF 规则并处理误报。 在这种情况下,你不会仅基于 comment 请求正文值执行作,这些值可能存在于同一 WAF 策略下的多个站点或应用中。

在包含另一个条件以在特定的请求 URI /api/Feedbacks/上匹配时,请确保此自定义规则真正适用于已审查的此显式用例。这样,WAF 引擎仍会检查和阻止相同的攻击(如果针对不同的条件执行)。

显示日志的屏幕截图。

浏览日志时,可以看到 ruleName_s 该字段包含为自定义规则 redirectcomment提供的名称。 在该 action_s 字段中,可以看到已为此事件执行 了重定向 作。 在 details_matches_s 字段中,可以看到这两个条件的详细信息已匹配。

禁用规则

另一种绕过误报的方法是禁用与 WAF 认为是恶意输入匹配的规则。 由于分析 WAF 日志并将规则缩小到 942110,因此可以在 Azure 门户中禁用它。 有关详细信息,请参阅 使用 Azure 门户自定义 Azure Web 应用程序防火墙规则

如果确定满足特定条件的所有请求都是合法请求,或者确定规则不适用于你的环境(例如禁用 SQL 注入规则,因为你具有非 SQL 后端),则禁用规则是一个好处。

禁用规则是一个全局设置,适用于与 WAF 策略关联的所有前端主机。 选择禁用规则时,可能会不对与 WAF 策略关联的任何其他前端主机进行保护或检测的情况下公开漏洞。

若要使用 Azure PowerShell 禁用托管规则,请参阅 PSAzureManagedRuleOverride 对象文档。 若要使用 Azure CLI,请参阅 az network front-door waf-policy managed-rules override 文档。

小窍门

记录对 WAF 策略所做的任何更改。 包括用于说明误报检测的示例请求。 说明为何添加了自定义规则、禁用了规则或规则集或添加了异常。 如果将来重新设计应用程序,可能需要验证更改是否仍然有效。 或者,可能需要审核或需要证明从其默认设置重新配置 WAF 策略的原因。

查找请求字段

通过使用 Fiddler 等浏览器代理,可以检查各个请求并确定调用网页的特定字段。 当你需要使用 WAF 中的排除列表从检查中排除某些字段时,此方法非常有用。

查找请求属性名称

在此示例中,将调用comment输入字符串的1=1字段。 此数据在 POST 请求的正文中传递。

显示 Fiddler 请求正文的屏幕截图。

可以排除此字段。 若要了解有关排除列表的详细信息,请参阅 Web 应用程序防火墙排除列表。 可以通过配置以下排除项来排除此情况中的评估:

显示排除规则的屏幕截图。

还可以检查防火墙日志以获取信息,以查看添加到排除列表所需的内容。 若要启用日志记录,请参阅 Azure Front Door 中的“监视指标和日志”。

检查文件中要检查的请求发生的小时防火墙日志 PT1H.json 。 这些文件PT1H.json在存储诊断日志的FrontDoorAccessLog存储帐户容器FrontDoorWebApplicationFirewallLog中可用。

了解 Azure 托管的规则集的工作原理后,你知道具有 action: Block 该属性的规则基于请求正文中匹配的数据阻止。 (有关详细信息,请参阅 Azure Front Door 中的 Azure Web 应用程序防火墙。可以在详细信息中看到它与模式(1=1)匹配,并且字段已命名 comment。 按照前面的相同步骤排除请求正文发布包含 comment的 args 名称。

查找请求标头名称

Fiddler 是查找请求标头名称的有用工具。 以下屏幕截图显示了此 GET 请求的标头,其中包括 Content-TypeUser-Agent。 还可以使用请求标头在 WAF 中创建排除项和自定义规则。

显示 Fiddler 请求标头的屏幕截图。

查看请求和响应标头的另一种方法是查看浏览器的开发人员工具,例如Microsoft Edge 或 Chrome。 可以选择 F12 或右键单击“ 检查>开发人员工具”。 选择“ 网络 ”选项卡。加载网页并选择要检查的请求。

显示网络检查器请求的屏幕截图。

如果请求包含 Cookie,请选择 “Cookie ”选项卡,在 Fiddler 中查看它们。 Cookie 信息还可用于在 WAF 中创建排除项或自定义规则。

异常评分规则

如果在优化 WAF 的过程中看到规则 ID 949110,则其状态指示请求被 异常评分 过程阻止。

通过搜索具有相同跟踪引用的日志条目来查看同一请求的其他 WAF 日志条目。 查看触发的每个规则。 按照本文中的指南优化每个规则。

警告

将新的托管规则集分配给 WAF 策略时,现有托管规则集(如规则状态、规则作和规则级别排除)的所有以前的自定义都将重置为新的托管规则集的默认值。 但是,在新的规则集分配期间,任何自定义规则和策略设置都将不受影响。

后续步骤