Java ReDos 易受攻击吗?
Is Java ReDos vulnerable?
我尝试使用 (a+)+
正则表达式和 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
(大量 a
)输入使用 jshell 重新创建 regular expression denial of service attack:
Pattern.compile("(a+)+")
.matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!")
.matches()
但是我每次尝试都很快完成。 Java 中的正则表达式实现与其他的不同吗?或者链接的维基百科页面有误?
(顺便说一句。我正在使用 Java 11,如果相关的话)
编辑:看起来它与 Java 版本相关,当我在 Java 8 上尝试它时,它挂起,但在 Java 9 和 11 中它立即工作。那些可能影响它的版本之间发生了什么变化?现在 Java 中的所有正则表达式都安全吗?
是否有特定的 Java JEP 更改了正则表达式的实现?我想知道什么样的正则表达式对于较新的 Java.
仍然是个问题
我目前是运行 Java 8 并且以下代码挂起:
Pattern.compile("(a|aa)+")
.matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab")
.matches()
鉴于您使用 Java 11 的方式(并且还使用 Java 9/10 对其进行了测试)并且发现它需要少量时间才能完成,显然有这些版本之间所做的更改。
通过查看 Java 11 中 Matcher
的源代码,我们发现 Java 8 中不存在以下添加:
/**
* Storage used by top greedy Loop node to store a specific hash set to
* keep the beginning index of the failed repetition match. The nodes
* themselves are stateless, so they rely on this field to hold state
* during a match.
*/
IntHashSet[] localsPos;
这个本地存储,以及添加的大量其他代码,似乎是 Java 9+ 中正则表达式的状态机比 [=21 中完成得快得多的主要原因之一=] 8及以下.
根据文章 RSPEC-2631,ReDoS 问题已在 Java 9 及更高版本中得到处理:
Java runtimes like OpenJDK 9+ are mitigating this problem by having additional protections in their implementation of regular expression evaluation. In those runtime the example above is not vulnerable.
我尝试使用 (a+)+
正则表达式和 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
(大量 a
)输入使用 jshell 重新创建 regular expression denial of service attack:
Pattern.compile("(a+)+")
.matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!")
.matches()
但是我每次尝试都很快完成。 Java 中的正则表达式实现与其他的不同吗?或者链接的维基百科页面有误?
(顺便说一句。我正在使用 Java 11,如果相关的话)
编辑:看起来它与 Java 版本相关,当我在 Java 8 上尝试它时,它挂起,但在 Java 9 和 11 中它立即工作。那些可能影响它的版本之间发生了什么变化?现在 Java 中的所有正则表达式都安全吗?
是否有特定的 Java JEP 更改了正则表达式的实现?我想知道什么样的正则表达式对于较新的 Java.
仍然是个问题我目前是运行 Java 8 并且以下代码挂起:
Pattern.compile("(a|aa)+")
.matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab")
.matches()
鉴于您使用 Java 11 的方式(并且还使用 Java 9/10 对其进行了测试)并且发现它需要少量时间才能完成,显然有这些版本之间所做的更改。
通过查看 Java 11 中 Matcher
的源代码,我们发现 Java 8 中不存在以下添加:
/**
* Storage used by top greedy Loop node to store a specific hash set to
* keep the beginning index of the failed repetition match. The nodes
* themselves are stateless, so they rely on this field to hold state
* during a match.
*/
IntHashSet[] localsPos;
这个本地存储,以及添加的大量其他代码,似乎是 Java 9+ 中正则表达式的状态机比 [=21 中完成得快得多的主要原因之一=] 8及以下.
根据文章 RSPEC-2631,ReDoS 问题已在 Java 9 及更高版本中得到处理:
Java runtimes like OpenJDK 9+ are mitigating this problem by having additional protections in their implementation of regular expression evaluation. In those runtime the example above is not vulnerable.