Web 应用程序防火墙排除列表

Azure 应用程序网关 Web 应用程序防火墙 (WAF) 可为 Web 应用程序提供保护。 本文介绍 WAF 排除列表的配置。 这些设置位于与应用程序网关关联的 WAF 策略中。 若要详细了解 WAF 策略,请参阅 Azure 应用程序网关上的 Azure Web 应用程序防火墙为应用程序网关创建 Web 应用程序防火墙策略

有时,WAF 可能会阻止要允许应用程序发出的请求。 WAF 排除列表允许你忽略 WAF 评估中的某些请求属性。 请求的其余部分照常评估。

例如,Active Directory 插入用于身份验证的令牌。 在请求标头中使用时,这些令牌可包含可能在 WAF 规则中触发误报检测的特殊字符。 通过将标头添加到排除列表,可以配置 WAF 来忽略标头,但 WAF 仍会评估请求的其余部分。

可以将排除项配置为在评估特定 WAF 规则时应用,或全局应用于所有 WAF 规则的评估。 排除规则适用于整个 Web 应用。

确定要排除的请求属性

配置 WAF 排除时,必须指定应从 WAF 评估中排除的请求属性。 可以为以下请求属性配置 WAF 排除:

  • 请求标头
  • 请求 Cookie
  • 请求属性名称(参数)可以添加为排除元素,例如:
    • 表单字段名称
    • JSON 实体
    • URL 查询字符串参数

可以指定请求标头、正文、cookie 或查询字符串属性的完全匹配项。 也可以指定部分匹配项。 使用以下运算符配置排除项:

  • 等于:此运算符用于完全匹配。 例如,要选择名为“bearerToken”的标头,请结合使用等号运算符和设为“bearerToken”的选择器 。
  • 开头为:此运算符与以指定选择器值开头的所有字段匹配。
  • 结尾:此运算符与以指定选择器值结尾的所有请求字段匹配。
  • 包含:此运算符与包含指定选择器值的所有请求字段匹配。
  • 等于任何值:此运算符与所有请求字段匹配。 * 将是选择器值。 例如,如果不知道给定匹配变量的确切值,但希望确保请求流量仍被排除在规则计算之外,将使用此运算符。

处理排除项时,WAF 引擎将根据下表进行区分大小写/不区分大小写的匹配。 此外,不允许将正则表达式用作选择器,也不支持 XML 请求正文。

请求正文部分 CRS 3.1 及更低版本 CRS 3.2 及更高版本
标头* 不区分大小写 不区分大小写
Cookie* 不区分大小写 区分大小写
查询字符串* 不区分大小写 区分大小写
URL 编码正文 不区分大小写 区分大小写
JSON 正文 不区分大小写 区分大小写
XML 正文 不支持 不支持
多部分正文 不区分大小写 区分大小写

*根据你所使用的应用程序,标头、Cookie 和查询参数的名称和值可以区分大小写或不区分大小写。

注意

有关详细信息和故障排除帮助,请参阅 WAF 故障排除

按键和值请求属性

配置排除项时,需要确定是要从 WAF 评估中排除键还是值。

例如,假设请求包含以下标头:

My-Header: 1=1

标头 (1=1) 的值可能会被 WAF 检测为攻击。 但是,如果知道这是方案的合法值,则可以为标头的值配置排除项。 为此,请使用 RequestHeaderValues 匹配变量、运算符 contains 和选择器 (My-Header)。 此配置停止对标头 My-Header 的所有值的评估。

注意

按键和值请求属性仅在 CRS 3.2 或更新版本和 Bot Manager 1.0 或更新版本中可用。

按名称请求属性与按值请求属性的工作方式相同,包含此功能是为了向后兼容 CRS 3.1 和更低版本。 建议按值使用请求属性,而不是按名称使用属性。 例如,使用 RequestHeaderValues 而不是 RequestHeaderNames。

相反,如果 WAF 将标头的名称 (My-Header) 检测为攻击,则可以使用 RequestHeaderKeys 请求属性为标头键配置排除项。 RequestHeaderKeys 属性仅在 CRS 3.2 或更新版本和 Bot Manager 1.0 或更新版本中可用。

请求属性示例

下表显示了如何构造给定匹配变量的排除项的一些示例。

要排除的属性 matchVariable selectorMatchOperator 示例选择器 示例请求 排除的内容
查询字符串 RequestArgKeys 等于 /etc/passwd URI:http://localhost:8080/?/etc/passwd=test /etc/passwd
查询字符串 RequestArgKeys EqualsAny 不可用 URI:http://localhost:8080/?/etc/passwd=test&.htaccess=test2 /etc/passwd.htaccess
查询字符串 RequestArgNames 等于 text URI:http://localhost:8080/?text=/etc/passwd /etc/passwd
查询字符串 RequestArgNames EqualsAny 不可用 URI:http://localhost:8080/?text=/etc/passwd&text2=.cshrc /etc/passwd.cshrc
查询字符串 RequestArgValues 等于 text URI:http://localhost:8080/?text=/etc/passwd /etc/passwd
查询字符串 RequestArgValues EqualsAny 不可用 URI:http://localhost:8080/?text=/etc/passwd&text2=.cshrc /etc/passwd.cshrc
请求正文 RequestArgKeys 包含 sleep 请求正文:{"sleep(5)": "test"} sleep(5)
请求正文 RequestArgKeys EqualsAny 不可用 请求正文:{".zshrc": "value", "sleep(5)":"value2"} .zshrcsleep(5)
请求正文 RequestArgNames 等于 test 请求正文:{"test": ".zshrc"} .zshrc
请求正文 RequestArgNames EqualsAny 不可用 请求正文:{"key1": ".zshrc", "key2":"sleep(5)"} .zshrcsleep(5)
请求正文 RequestArgValues 等于 test 请求正文:{"test": ".zshrc"} .zshrc
请求正文 RequestArgValues EqualsAny 不可用 请求正文:{"key1": ".zshrc", "key2":"sleep(5)"} .zshrcsleep(5)
Header RequestHeaderKeys 等于 X-Scanner 标头:{"X-Scanner": "test"} X-scanner
Header RequestHeaderKeys EqualsAny 不可用 标头:{"X-Scanner": "test", "x-ratproxy-loop": "value"} X-Scannerx-ratproxy-loop
Header RequestHeaderNames 等于 head1 标头:{"head1": "X-Scanner"} X-scanner
Header RequestHeaderNames EqualsAny 不可用 标头:{"head1": "myvar=1234", "User-Agent": "(hydra)"} myvar=1234(hydra)
Header RequestHeaderValues 等于 head1 标头:{"head1": "X-Scanner"} X-scanner
Header RequestHeaderValues EqualsAny 不可用 标头:{"head1": "myvar=1234", "User-Agent": "(hydra)"} myvar=1234(hydra)
Cookie RequestCookieKeys 包含 /etc/passwd 标头:{"Cookie": "/etc/passwdtest=hello1"} /etc/passwdtest
Cookie RequestCookieKeys EqualsAny 不可用 标头:{"Cookie": "/etc/passwdtest=hello1", "Cookie": ".htaccess=test1"} /etc/passwdtest.htaccess
Cookie RequestCookieNames 等于 arg1 标头:{"Cookie": "arg1=/etc/passwd"} /etc/passwd
Cookie RequestCookieNames EqualsAny 不可用 标头:{"Cookie": "arg1=/etc/passwd", "Cookie": "arg1=.cshrc"} /etc/passwd.cshrc
Cookie RequestCookieValues 等于 arg1 标头:{"Cookie": "arg1=/etc/passwd"} /etc/passwd
Cookie RequestCookieValues EqualsAny 不可用 标头:{"Cookie": "arg1=/etc/passwd", "Cookie": "arg1=.cshrc"} /etc/passwd.cshrc

注意

如果使用 selectorMatchOperator EqualsAny 创建排除项,那么在创建排除项时,在选择器字段中填入的任何内容都会被后端转换为“*”。

排除范围

可以将排除项配置为应用于一组特定的 WAF 规则、规则集或全局应用于所有规则。

提示

最好使排除范围尽可能窄和具体,以避免意外地为攻击者留出空间来攻击系统。 如果需要添加排除规则,请尽可能使用基于规则的排除项。

基于规则的排除项

可以为特定规则、规则组或规则集配置排除项。 必须指定应用排除的规则。 还需要指定应从 WAF 评估中排除的请求属性。 要排除完整的规则组,只需提供 ruleGroupName 参数,rules 参数仅在希望将排除限制为组的特定规则时有用。

使用 OWASP (CRS) 规则集版本 3.2 或更高版本或者 Bot Manager 规则集版本 1.0 或更高版本时,可以使用按规则排除。

示例

假设你希望 WAF 忽略 User-Agent 请求标头的值。 User-Agent 请求标头包含特征性字符,网络协议对等方可以通过这些字符了解请求软件用户代理的应用程序类型、操作系统、软件供应商或软件版本。 有关详细信息,请参阅 User-Agent

在许多情况下,需要禁用对此标头进行评估的功能。 WAF 可能会将检测到的某个字符串定性为恶意字符串。 例如,User-Agent 标头可能在字符串中包含经典的 SQL 注入攻击 x=x。 在某些情况下,这可能是合法的流量。 因此,可能需要将此标头从 WAF 评估中排除。

可以使用以下方法从所有 SQL 注入规则的评估中排除 User-Agent 标头:

若要使用 Azure 门户配置按规则排除,请执行以下步骤:

  1. 导航到 WAF 策略,然后选择“托管规则”。

  2. 选择“添加排除项”。

    Screenshot of the Azure portal that shows how to add a new per-rule exclusion for the W A F policy.

  3. 在“适用范围”中,选择要应用排除项的 CRS 规则集,例如 OWASP_3.2。

    Screenshot of the Azure portal that shows the per-rule exclusion configuration for the W A F policy.

  4. 选择“添加规则”,然后选择要向其应用排除项的规则。

  5. 配置匹配变量、运算符和选择器。 再选择“保存”。

可以配置多个排除项。

还可以按规则 942270 从评估中排除 User-Agent 标头:

按照前面示例中所述步骤操作,并在步骤 4 中选择规则 942270。

全局排除项

可以配置排除项以应用于所有 WAF 规则。

示例

假设你要排除通过 URL 在请求中传递的 user 参数中的值。 例如,假设在你的环境中,user 查询字符串参数常常包含某个字符串,而 WAF 会将该字符串视为恶意内容并将其阻止。 可以排除名称以单词 user 开头的所有查询字符串参数,以便 WAF 不会评估字段的值。

以下示例演示如何从评估中排除 user 查询字符串参数:

若要通过使用 Azure 门户来配置全局排除项,请执行以下步骤:

  1. 导航到 WAF 策略,然后选择“托管规则”。

  2. 选择“添加排除项”。

    Screenshot of the Azure portal that shows how to add a new global exclusion for the W A F policy.

  3. 在“适用范围”中,选择“全局”

    Screenshot of the Azure portal that shows the global exclusion configuration for the W A F policy.

  4. 配置匹配变量、运算符和选择器。 再选择“保存”。

可以配置多个排除项。

因此,如果 WAF 扫描 URL http://www.contoso.com/?user%3c%3e=joe,它不会评估字符串 joe,但仍会评估参数名称 user%3c%3e

后续步骤