跳到主内容
快讯直播
AI智模界
AI 词典

ReDoS:一条无害正则如何打满 CPU

ReDoS(Regular Expression Denial of Service,正则表达式拒绝服务)指的是:一条语法完全正确、平时跑得好好的正则,在某种特定输入下触发「灾难性回溯」,让 CPU 在一个核上跑到 100%,把服务拖垮。

回溯是怎么变成爆炸的

多数编程语言用的正则引擎是 NFA(非确定性有限自动机)实现,靠回溯(backtracking)来匹配:从左往右走,遇到分支先试第一条路,走不通就退回来试下一条。

打个比方:你在核对一叠账单,每笔钱都有「算进去」和「不算进去」两种可能。如果最后总和不对,你只能把每一种组合都重算一遍——n 笔账单就是 2ⁿ 种组合。回溯引擎就是这么干的。

看这条几乎人人写过的正则:

```

^(a+)+$

```

它匹配 aaaa...a(一长串 a)没问题。但如果结尾多一个其他字符,比如 aaaa...a!,引擎必须先认定「不匹配」,而 a+ 外面还套了 +,同一段 a 有指数多种切分方式(内层吃几个、外层吃几个)。结尾失败后,它得把所有切分方式全试一遍才敢下结论。输入每多一个 a,耗时翻一倍——二十几个字符就能卡住好几秒。

危险的不是正则写错了,而是它只在长输入 + 结尾失败时引爆。日常测试用小字符串,永远测不出来。

和相邻概念的区别

维度普通慢正则ReDoS
变慢的原因单次扫描常数大,如全表扫回溯次数随输入长度指数增长
输入变长后的表现大致线性增长长度每加 1,耗时约翻倍
什么时候暴露一直慢,压测就能发现小输入正常,恶意输入瞬间雪崩

它和 SQL 注入、XSS 的区别在于:ReDoS 不窃取数据、不篡改内容,只是把计算资源烧光,属于可用性攻击。也和「算法复杂度写错」不同——攻击者能主动构造那条最坏输入。

对实际工作的意义

凡是有用户可控的字符串进入正则,就要假设对方会构造最坏输入。几个立即可用的动作:

  • 限制输入长度。正则之前先截断,几十个字符的输入造不出指数爆炸。
  • 设置超时或中断机制,别让一次匹配无限拖住线程。
  • 换引擎。基于自动机的引擎(如 RE2、Go 标准库的 regexp)保证线性时间,代价是不支持反向引用和环视。
  • 改写法。避免嵌套量词 (a+)+、(.*)*、(\w+\s?)* 这类结构;用字符类替代宽泛的 .;能让分支互斥就别让它们重叠;部分引擎支持占有量词或原子组,可以关掉回溯。

对不写代码的人来说,这件事的体感是:某个接口突然全部超时,CPU 打满,重启能好一阵,过一会儿又复发——很可能就是日志过滤、表单校验或者一个爬虫解析规则里藏了这么一条正则。

顺带提醒:在 LLM 应用里,正则常被用来解析模型输出、脱敏、校验工具参数,如果这些环节的输入来自外部,风险完全一样。具体引擎的能力边界,以官方文档为准。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。