SonarQube 显示正则表达式拒绝服务 (ReDoS)

rah*_*hul 23 javascript regex sonarqube

我在 JavaScript 中使用正则表达式验证日期,但是当我运行 SonarQube 进行代码分析时。它将正则表达式显示为一个安全漏洞。

示例1:

以下是正则表达式模式(链接到正则表达式来源/sf/answers/1085341421/):

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
Run Code Online (Sandbox Code Playgroud)

示例2:

对于浮动值,我使用了下面的正则表达式

^\d{1,5}(?:\.\d{1,5})?$
Run Code Online (Sandbox Code Playgroud)

SonarQube 抛出相同的安全错误,我尝试了各种不同的正则表达式模式,但它不起作用。

sep*_*p2k 52

热点与漏洞

首先请注意,SonarQube 正在通知您有关安全热点的信息,而不是漏洞。这意味着什么(引用自文档):

安全热点突出显示开发人员需要检查的安全敏感代码段。经过审查,您会发现不存在威胁​​,或者需要应用修复程序来保护代码。

[...]

使用热点,会突出显示一段安全敏感的代码,但整体应用程序安全性可能不会受到影响。由开发人员检查代码以确定是否需要修复来保护代码。

这里重要的一点是 SonarQube 并没有告诉您出现了问题。它告诉您应该仔细查看代码以确定是否有问题。

换句话说,它告诉您您的正则表达式可能容易受到 ReDoS 攻击,但事实并非如此。如果您检查代码并确定不存在漏洞,那么完全可以忽略该问题而不进行任何更改。

那么为什么 SonarQube 要求您检查这段代码呢?

SonarQube 实际上并不检测正则表达式是否容易受到 ReDoS 的攻击(这就是为什么它被标记为安全热点,而不是漏洞)。相反,它会标记所有重要的正则表达式,并提醒您检查它们以确定它们是否容易受到攻击。正如规则文档中所解释的,它认为任何包含多个字符的正则表达式都是重要的*+{

由于根据该标准,您的两个正则表达式都不是平凡的,因此两者都被标记。

更新:以上内容适用于编写此答案时存在的 ReDoS 规则。同时该规则已被弃用,并被一条新规则所取代,该规则应该只抱怨实际上具有超线性运行时的正则表达式。新规则不会抱怨这个问题中的正则表达式。

那么你的代码容易受到攻击吗?

不,你的正则表达式都不容易受到攻击。事实上,这两个表达式中使用的唯一重复运算符是{}and 由于您在所有情况下都提供了上限,因此甚至不存在任何无限重复。

然而,我想说你的第一个正则表达式足够复杂,足以成为可读性和维护的噩梦。因此,您应该考虑用另一种方法替换它(例如将字符串拆分为单独的数字并检查每个数字是否在所需的范围内)。

那你该怎么办?

确定正则表达式不易受到攻击后,您应该消除该热点。

在评论中指出,如果将正则表达式字符串拆分为多个连接的字符串或将其移动到变量中,该消息将会消失。有效的原因很简单,它会欺骗 SonarQube 找不到正则表达式。因此,这种更改不会使您的代码变得更好或更安全,它只会让 SonarQube 感到困惑,并且绝不比直接忽略该消息更好。通常不建议仅仅为了让静态分析工具关闭而混淆代码。