反模式:在 RegularExpressionProtection 政策中使用贪婪限定符

您正在查看 ApigeeApigee Hybrid 文档。
查看 Apigee Edge 文档。

RegularExpressionProtection 政策定义在输入参数或流变量中在运行时评估的正则表达式。您通常使用此政策来防范 SQL 或 JavaScript 注入等内容威胁,或检查是否有格式错误的请求参数(如电子邮件地址或网址)。

您可以为正则表达式、查询参数、表单参数、标头、XML 元素(使用 XPath 定义的 XML 载荷中)、JSON 对象属性(使用 JSONPath 定义的 JSON 载荷中)定义正则表达式。

以下示例 RegularExpression 政策保护后端免受 SQL 注入攻击:

<!-- /antipatterns/examples/greedy-1.xml -->
<RegularExpressionProtection async="false" continueOnError="false" enabled="true"
  name="RegexProtection">
    <DisplayName>RegexProtection</DisplayName>
    <Properties/>
    <Source>request</Source>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <QueryParam name="query">
      <Pattern>[\s]*(?i)((delete)|(exec)|(drop\s*table)|
        (insert)|(shutdown)|(update)|(\bor\b))</Pattern>
    </QueryParam>
</RegularExpressionProtection>

反模式

默认限定符(*+?)性质相似:它们开始与尽可能最长的序列匹配。如果未找到匹配项,它们会逐步反向跟踪,以尝试匹配模式。如果与模式匹配的结果字符串非常短,则使用贪婪限定符所用的时间可能比所需时间长。如果载荷很大(数十或数百 KB),则尤其如此。

以下示例表达式使用 .* 的多个实例,这些实例是贪婪运算符:

<Pattern>.*Exception in thread.*</Pattern>

在此示例中,RegularExpressionProtection 政策首先尝试匹配尽可能最长的序列(整个字符串)。如果未找到匹配项,则政策会逐步反向跟踪。如果匹配的字符串接近载荷的起始或中间位置,则相比 .*? 等勉强限定符或 .*+ 等不常见的所有格限定符,使用 .* 等贪婪限定符可能需要花费更多的时间和处理能力。

勉强限定符(如 X*?X+?X??)首先尝试从载荷的开头匹配单个字符并逐步添加字符。所有格限定符(如 X?+X*+X++)会尝试仅匹配整个载荷一次。

以上述模式的以下示例文本为例:

Hello this is a sample text with Exception in thread
with lot of text after the Exception text.

在这种情况下,使用贪婪 .* 将不起作用。模式 .*Exception in thread.* 执行了 141 个步骤来进行匹配。如果您改用模式 .*?Exception in thread.*(使用勉强限定符),则结果将仅是 55 个步骤。

影响

将通配符 (*) 等贪婪限定符与 RegularExpressionProtection 政策搭配使用可能会导致:

  • 对于中等载荷大小(最大 1MB)的 API 请求,总体延迟时间会增加
  • 完成 RegularExpressionProtection 政策执行的时间更长
  • 如果预定义超时期限在 Apigee 路由器上已过,则含大型载荷 (>1MB) 的 API 请求会失败并显示 504 网关超时错误
  • 消息处理器上的 CPU 利用率较高,因为大量处理可能会进一步影响其他 API 请求

最佳做法

  • 避免在正则表达式中将 .* 等贪婪限定符与 RegularExpressionProtection 政策搭配使用。因此,尽可能使用 .*? 等勉强限定符或 .*+ 等不常见的所有格限定符。

更多详情