SonarQube 显示正则表达式拒绝服务 (ReDoS)
SonarQube showing Regular expression Denial of Service (ReDoS)
我在 JavaScript 中使用正则表达式验证日期,但是当我 运行 SonarQube 进行代码分析时。它将正则表达式显示为安全漏洞。
示例 1:
下面是正则表达式模式(link 到正则表达式的来源 ):
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2(?:(?:(?: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]))(?:(?:1[6-9]|[2-9]\d)?\d{2})$
示例 2:
对于浮动值,我使用了下面的正则表达式
^\d{1,5}(?:\.\d{1,5})?$
SonarQube 抛出相同的安全错误,我尝试了各种不同的正则表达式模式,但它不起作用。
热点与漏洞
首先请注意,SonarQube 通知您的是安全热点,而不是漏洞。这意味着(引用自the docs):
A Security Hotspot highlights a security-sensitive piece of code that the developer needs to review. Upon review, you'll either find there is no threat or you need to apply a fix to secure the code.
[...]
With a Hotspot, a security-sensitive piece of code is highlighted, but the overall application security may not be impacted. It's up to the developer to review the code to determine whether or not a fix is needed to secure the code.
这里要注意的重要一点是 SonarQube 不会告诉您有问题。它告诉你应该仔细查看代码以确定是否有问题。
换句话说,它是在告诉您您的正则表达式 可能 容易受到 ReDoS 攻击,但事实并非如此。如果您查看代码并确定不存在漏洞,则完全可以忽略该问题而不进行任何更改。
那么,SonarQube 究竟为什么要您查看此代码?
SonarQube 实际上不会检测正则表达式是否易受 ReDoS 攻击(这就是为什么它被标记为安全热点,而不是漏洞)。相反,它会标记所有重要的正则表达式并提醒您检查它们以确定它们是否易受攻击。正如 the documentation of the rule 中所解释的,它认为任何正则表达式都是重要的,其中包含多次出现的任何字符 *+{
.
由于您的两个正则表达式都符合该标准,因此都被标记了。
更新:以上内容适用于撰写此答案时存在的 ReDoS 规则。该规则同时已被弃用,取而代之的是一条新规则,该规则应该只抱怨实际上具有超线性运行时的正则表达式。新规则没有抱怨这个问题中的正则表达式。
那么您的代码是否存在漏洞?
不,您的两个正则表达式都不容易受到攻击。事实上,这两个表达式中唯一使用的重复运算符是 {}
,并且由于您在所有情况下都提供了上限,因此甚至没有任何无限制的重复。
但是,我会说您的第一个正则表达式非常复杂,足以成为可读性和维护方面的噩梦。所以你应该考虑用另一种方法替换它(例如将字符串拆分为单独的数字并检查每个数字是否在所需范围内)。
那你该怎么办?
确定正则表达式不易受攻击后,您应该关闭热点。
在评论中有人指出,如果您将正则表达式字符串拆分为多个连接的字符串或将其移动到一个变量中,该消息就会消失。起作用的原因很简单,它会诱使 SonarQube 找不到正则表达式。因此,这种更改不会使您的代码变得更好或更安全,它只会混淆 SonarQube,并且绝不比忽略消息更可取。通常不建议混淆您的代码只是为了让您的静态分析工具闭嘴。
我在 JavaScript 中使用正则表达式验证日期,但是当我 运行 SonarQube 进行代码分析时。它将正则表达式显示为安全漏洞。
示例 1:
下面是正则表达式模式(link 到正则表达式的来源 ):
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2(?:(?:(?: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]))(?:(?:1[6-9]|[2-9]\d)?\d{2})$
示例 2:
对于浮动值,我使用了下面的正则表达式
^\d{1,5}(?:\.\d{1,5})?$
SonarQube 抛出相同的安全错误,我尝试了各种不同的正则表达式模式,但它不起作用。
热点与漏洞
首先请注意,SonarQube 通知您的是安全热点,而不是漏洞。这意味着(引用自the docs):
A Security Hotspot highlights a security-sensitive piece of code that the developer needs to review. Upon review, you'll either find there is no threat or you need to apply a fix to secure the code.
[...]
With a Hotspot, a security-sensitive piece of code is highlighted, but the overall application security may not be impacted. It's up to the developer to review the code to determine whether or not a fix is needed to secure the code.
这里要注意的重要一点是 SonarQube 不会告诉您有问题。它告诉你应该仔细查看代码以确定是否有问题。
换句话说,它是在告诉您您的正则表达式 可能 容易受到 ReDoS 攻击,但事实并非如此。如果您查看代码并确定不存在漏洞,则完全可以忽略该问题而不进行任何更改。
那么,SonarQube 究竟为什么要您查看此代码?
SonarQube 实际上不会检测正则表达式是否易受 ReDoS 攻击(这就是为什么它被标记为安全热点,而不是漏洞)。相反,它会标记所有重要的正则表达式并提醒您检查它们以确定它们是否易受攻击。正如 the documentation of the rule 中所解释的,它认为任何正则表达式都是重要的,其中包含多次出现的任何字符 *+{
.
由于您的两个正则表达式都符合该标准,因此都被标记了。
更新:以上内容适用于撰写此答案时存在的 ReDoS 规则。该规则同时已被弃用,取而代之的是一条新规则,该规则应该只抱怨实际上具有超线性运行时的正则表达式。新规则没有抱怨这个问题中的正则表达式。
那么您的代码是否存在漏洞?
不,您的两个正则表达式都不容易受到攻击。事实上,这两个表达式中唯一使用的重复运算符是 {}
,并且由于您在所有情况下都提供了上限,因此甚至没有任何无限制的重复。
但是,我会说您的第一个正则表达式非常复杂,足以成为可读性和维护方面的噩梦。所以你应该考虑用另一种方法替换它(例如将字符串拆分为单独的数字并检查每个数字是否在所需范围内)。
那你该怎么办?
确定正则表达式不易受攻击后,您应该关闭热点。
在评论中有人指出,如果您将正则表达式字符串拆分为多个连接的字符串或将其移动到一个变量中,该消息就会消失。起作用的原因很简单,它会诱使 SonarQube 找不到正则表达式。因此,这种更改不会使您的代码变得更好或更安全,它只会混淆 SonarQube,并且绝不比忽略消息更可取。通常不建议混淆您的代码只是为了让您的静态分析工具闭嘴。