如何在PHP中触发Regex拒绝服务?

时间:2016-05-22 18:55:13

标签: php regex security preg-match denial-of-service

如何使用邪恶的正则表达式(例如(a +)+ )使用preg_match()函数触发Regex-DOS?

例如,我有以下情况:

preg_match('/(a+)+/',$input);

如果我可以控制$input,我怎样才能触发 DOS攻击或达到php中preg_*函数的回溯限制

我怎么能用以下表达式做到这一点?

([a-zA-Z]+)*
(a|aa)+
(a|a?)+
(.*a){x} | for x > 10 

1 个答案:

答案 0 :(得分:3)

无法在(a+)+([a-zA-Z]+)*(a|aa)+(a|a?)+上触发ReDOS,因为没有什么可以导致匹配失败并在问题发生后触发回溯正则表达式的一部分。

如果您稍微修改正则表达式,例如adding b$ after each of the regex above,那么您可以使用aaa ... aabaa ... {{1}之类的输入触发灾难性回溯}。

根据引擎的实施和优化,有些情况下我们预计会发生灾难性的回溯,但引擎并未表现出任何此类行为的迹象。

例如,给定aa和输入(a+)+b ... aaaPCRE fails the match outright,因为它有一个优化,可以检查输入字符串中的所需字符正确地开始比赛。

了解引擎的作用,我们可以使用输入aac ... aaa throw off its early detection并让引擎展示灾难性的回溯。

对于aacb,可以触发ReDOS,因为它具有小于(.*a){x}次迭代的失败条件。给定输入字符串x ... aaaa或更多字符x),正则表达式会继续尝试a&#39的所有排列; s在字符串的末尾,因为它从字符串的末尾回溯。因此,正则表达式的复杂性是O(2 x )。知道了这一点,我们可以看出,当a数字越大let's say 20时效果越明显。顺便说一下,这是一种罕见的情况,其中匹配的字符串具有最差的案例复杂性。