无需登录 数据私有 本地保存

正则回溯灾难演示 - Catastrophic Backtracking

16
0
0
0

正则回溯灾难演示

直观感受灾难性回溯(Catastrophic Backtracking)如何让正则引擎瞬间崩溃 — 使用 Web Worker 安全执行,不会卡死页面

经典预设案例
/ /
最多5000字符。对于灾难性回溯演示,几十个字符就足够了。

发生了什么? 当正则引擎遇到嵌套量词(如 (a+)+)且匹配失败时,它会尝试所有可能的拆分组合。对于长度为 n 的输入, 回溯次数可达 O(2n) 级别,导致执行时间指数级爆炸。此工具使用 Web Worker 隔离执行, 3秒超时自动中断,保护您的浏览器不会卡死。

常见问题 & 知识点
灾难性回溯是正则表达式引擎在尝试匹配失败时,因嵌套量词或过度贪婪而导致需要探索指数级数量的可能路径的现象。 正则引擎(特别是使用回溯算法的NFA引擎,如JavaScript、Python、Java等)在遇到如 (a+)+b 匹配 aaaaaaaaac 时, 会尝试将连续的a以不同方式分配给内外量词(如1+7、2+6、3+5...),每种分配失败后又尝试不同的回溯路径。 对于na,可能的拆分方式约为 2n-1 种,导致执行时间随输入长度呈指数级增长。 当输入仅20个字符时,回溯次数就可能超过百万次,使引擎完全卡死。
以下是最常见的危险模式

(X+)+(X*)+ — 量词嵌套量词(最经典)
(X+X+)+ — 多个量词组嵌套
([X]+)* — 字符组量词被外层量词包裹
(X|X)*Y — 交替嵌套,特别是交替项有重叠时
(.*){n} — 点号重复固定次数,但内部贪婪
.*.* — 多个贪婪点号重叠

关键特征:存在多种方式匹配同一段文本(歧义),且当匹配最终失败时引擎必须穷尽所有可能。
在JavaScript中,正则执行是同步阻塞的,危险的正则可能直接卡死整个页面甚至浏览器标签页。推荐的安全措施:

1. Web Worker(推荐):将正则执行放入Worker线程,主线程设置超时(如3秒),超时后terminate() Worker。这是本工具使用的方法。
2. 输入长度限制:对用户输入的测试字符串进行长度限制。
3. 静态分析:在执行前检测正则中是否存在嵌套量词等危险模式。
4. 使用RE2/V8实验性功能:某些环境支持保证线性时间的正则引擎(如Google RE2),但JavaScript原生不支持。
5. 服务端执行:将正则匹配放到后端执行,配合进程级别的超时控制(如set_time_limit或容器超时)。
优化策略

消除嵌套量词:将 (a+)+ 改写为 a+(如果不需要捕获组)
使用原子组(如果引擎支持):(?>a+)b 禁止在组内回溯
使用占有量词a++b 匹配后不释放(JavaScript不支持,但可模拟)
减少歧义:确保每个字符只有一种匹配方式
使用字符类替代点号.* 改为 [^x]* 更精确
锚定正则:使用 ^$ 限制匹配范围
非贪婪量词.*? 有时比 .* 更安全(但不总是)
重写正则逻辑:将复杂正则拆分为多个简单正则分步匹配
JavaScript使用回溯式NFA引擎,具有以下特点:

不支持原子组 (?>...)占有量词 ++*+
不支持 possessive quantifiers,无法在语法层面阻止回溯
• 支持后行断言(ES2018+):(?<=...)(?<!...)
• 支持命名捕获组(?<name>...)
• 支持Unicode属性\p{...}(需u标志)
g标志会维护lastIndex,多次调用需注意重置
• V8引擎(Chrome/Node.js)对某些模式有内部优化,但不能完全依赖

由于缺乏原子组,JavaScript在面对回溯灾难时比其他语言(如PHP PCRE、Java)更加脆弱。
著名案例

Cloudflare 2019年全球中断:一个WAF规则中的正则 (?:(?:\"|'|\]|\}|\\|\d|(?:nan|infinity|true|false|null|undefined|symbol|math)|\`|\-|\+)+[)]*;?((?:\s|-|~|!|{}|\|\||\+)*.*(?:.*=.*))) 导致了灾难性回溯,造成全球CDN服务中断约30分钟。
Stack Overflow 2016年:一个用于检测代码的正则表达式在处理超长行时导致CPU 100%。
OWASP:将正则注入(ReDoS — Regular Expression Denial of Service)列为Web应用安全威胁。

教训:永远不要信任用户提供的正则表达式;对所有正则执行设置超时机制;在部署前使用工具检测潜在的回溯灾难风险。
ReDoS(Regular Expression Denial of Service)是一种利用灾难性回溯使服务器CPU资源耗尽的攻击方式。攻击者提交精心构造的输入字符串, 配合已知的危险正则表达式(或应用自身的正则),导致匹配操作长时间运行,耗尽服务器资源。

防护措施
• 对所有正则执行添加超时限制
• 使用安全的线性时间正则引擎(如RE2、Rust regex crate)
• 对用户输入进行长度限制
• 在生产环境中审计所有正则表达式,识别并修复危险模式
• 使用专门的ReDoS检测工具(如rxxrvuln-regex-detector
• 在API网关层面设置请求超时和速率限制