正则表达式 (Regular Expression)
正则表达式拒绝服务攻击 (ReDoS) 是一种攻击类型,它利用某些正则表达式处理时间极长这一特性,导致应用程序或服务无响应或崩溃。
摘要 (Summary)
工具 (Tools)
- tjenkinson/redos-detector - 一个 CLI 工具和库,可以确定正则表达式模式是否能免受 ReDoS 攻击。支持在浏览器、Node 和 Deno 中运行。
- doyensec/regexploit - 查找易受 ReDoS(正则表达式拒绝服务)攻击的正则表达式。
- devina.io/redos-checker - 检查正则表达式中潜在的拒绝服务漏洞。
方法论 (Methodology)
邪恶正则 (Evil Regex)
邪恶正则通常包含:
- 带有重复的分组
- 在重复的分组内部包含:
- 重复
- 带有重叠的选择 (Alternation)
示例:
(a+)+([a-zA-Z]+)*(a|aa)+(a|a?)+(.*a){x}其中 x > 10
这些正则表达式可以使用 aaaaaaaaaaaaaaaaaaaa! (20 个 'a' 后跟一个 '!') 来进行攻击。
对于此输入,正则引擎会尝试所有可能的分组方式来匹配 a 字符,直到最后意识到因为 ! 的存在匹配失败。这会导致回溯尝试的次数爆炸式增长。
回溯限制 (Backtrack Limit)
正则表达式中的回溯发生在正则引擎尝试匹配模式但遇到不匹配时。引擎随后会回溯到上一个匹配位置,并尝试另一条替代路径来寻找匹配。这个过程可能会重复多次,在使用复杂模式和处理大型输入字符串时尤为明显。
PHP PCRE 配置选项:
| 名称 | 默认值 | 备注 |
|---|---|---|
| pcre.backtrack_limit | 1000000 | 对于 PHP < 5.3.7 为 100000 |
| pcre.recursion_limit | 100000 | / |
| pcre.jit | 1 | / |
有时可以强制正则表达式超过 100,000 次递归,这将导致 ReDoS 并使 preg_match 返回 false:
$pattern = '/(a+)+$/';
$subject = str_repeat('a', 1000) . 'b';
if (preg_match($pattern, $subject)) {
echo "发现匹配";
} else {
echo "未发现匹配";
}