You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
图片第一行显示的 Regular Expression Denial of Service 成功引起了我的注意。Denial of Service 我们都知道,拒绝服务攻击,以一种简单暴力的方式消耗被攻击者的资源,让其服务到达不可用的地步,比如常见的 DDoS。那么 Regular Expression Denial of Service (以下简称 ReDoS) 通过字面意思理解应该就是:正则表达式拒绝服务攻击。
正则表达式的匹配通常是比较耗费计算性能的,尤其是当正则表达式中包含复杂的子表达式的重复匹配、或者重复匹配的简单子表达式也可能匹配另一个子表达式的时候。当一个正则表达式存在这些问题的时候,一些用户的输入可能会导致匹配运行效率非常低下,从而引发 DoS (因为计算资源可能被耗尽)。
从 npm audit 说起
今天尝试用
npm audit
在项目里跑了一下,发现了很多类似下面的错误:Regular Expression Denial of Service (ReDoS)
图片第一行显示的
Regular Expression Denial of Service
成功引起了我的注意。Denial of Service
我们都知道,拒绝服务攻击,以一种简单暴力的方式消耗被攻击者的资源,让其服务到达不可用的地步,比如常见的DDoS
。那么Regular Expression Denial of Service
(以下简称ReDoS
) 通过字面意思理解应该就是:正则表达式拒绝服务攻击。正则表达式的匹配通常是比较耗费计算性能的,尤其是当正则表达式中包含复杂的子表达式的重复匹配、或者重复匹配的简单子表达式也可能匹配另一个子表达式的时候。当一个正则表达式存在这些问题的时候,一些用户的输入可能会导致匹配运行效率非常低下,从而引发 DoS (因为计算资源可能被耗尽)。
Node.js 中的 ReDoS
说了这么多,也许不如一个例子能够把我的意思表达的更清楚:
上面正则表达式看起来非常简单,但是存在我们上面说的可能导致匹配效率低下的问题。可以看到这个简单的匹配耗时大约 5 秒钟,对于 Node.js 这种基于 event loop 的单进程服务器来说是不可接受的。
解决办法
尽量使用社区开源的正则表达式。如果你正在做一些常规的字符串校验,比如邮件、电话号码的匹配,那么可以尝试 validator.js。
如果需要自己编写正则表达式,可以使用 safe-regex 这样的工具来校验自己的正则表达式是否有潜在的问题,也可以使用 regex101 在线进行检验 (regex101 功能十分强大,界面也很清新,另外还提供了 debugger 功能),比如上面的这个例子在 regex101 里会被检测到有 “灾难性的回溯”(Catastrophic backtracking) 问题:
附录
出于好奇,用 Rust 写了跟上面 Node.js 例子中的正则表达式,下面是执行的结果:
Rust 好像对于正则表达式这些潜在的性能问题有一些预防的解决方案 (只调用回溯引擎的混合解决方案),具体我也不是太了解,有兴趣的小伙伴可以自行查资料。不过 Rust 确实是非常快的,真的要抽空好好学习 Rust 咯,后面用得到的地方还是很多的。
The text was updated successfully, but these errors were encountered: