我最近意识到正则表达式拒绝服务攻击,并决定根除所谓的“邪恶”正则表达式模式,只要我能在代码库中找到它们,或者至少是那些用于用户输入的模式。上面的OWASP链接和wikipedia中给出的示例很有帮助,但它们不能很好地用简单的术语解释问题。
邪恶正则表达式的描述,来自维基百科:
举个例子,同样来自维基百科:
(a)
这是一个没有更简单解释的问题吗?我正在寻找一种在编写正则表达式时更容易避免这个问题的方法,或者在现有的代码库中找到它们。
邪恶的正则表达式总是由于相应NFA中的模糊性造成的,您可以使用诸如regexper之类的工具将其可视化。
这里有一些形式的歧义。不要在正则表达式中使用这些。
(a)
(又称“星高”)我写了这篇关于超线性正则表达式的论文。它包括大量参考其他与正则表达式相关的研究。
你所谓的“邪恶”正则表达式是一个表现出灾难性回溯的正则表达式。链接页面(我写的)详细解释了这个概念。基本上,灾难性的回溯发生在正则表达式无法匹配时,同一正则表达式的不同排列可以找到部分匹配。正则表达式引擎然后尝试所有这些排列。如果您想检查您的代码并检查您的正则表达式,请查看以下三个关键问题:
>
包含带有量词的标记的组不能有自己的量词,除非组内的量化标记只能与其他相互排斥的标记匹配。这确保了外部量词的迭代次数越少,内部量词的迭代次数越多,就无法与外部量词的迭代次数越多,内部量词的迭代次数越少的文本匹配。这就是JDB的答案中说明的问题。
当我在写我的答案时,我认为这值得在我的网站上发表一篇完整的文章。现在这也是在线的。
因为计算机完全按照你告诉他们的去做,即使这不是你的意思或者完全不合理。如果您要求正则表达式引擎证明,对于某些给定输入,给定模式存在或不存在匹配,那么无论必须测试多少种不同的组合,该引擎都会尝试这样做。
以下是一个简单的模式,灵感来自OP文章中的第一个示例:
^((ab)*)+$
正则表达式引擎尝试类似于(abababababab)
的东西,并且在第一次尝试时找到匹配项。
但是我们把活动扳手扔进去:
阿巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴巴
发动机将首先尝试(abababababababab)
,但由于额外的a
而失败。这会导致灾难性的回溯,因为我们的模式(ab)*
,出于诚意,将释放其中一个捕获(它将“回溯”),并让外部模式重试。对于我们的正则表达式引擎,它看起来像这样:
(ababababababab)
-Nope(abababababababab)(ab)
-Nope(abababababababababab)(abab)
-Nope(ababababababababab)(ab)(ab)
-Nope(ababababababababababababababababababababababababab)(abab)<(ababababababab)(abab)(abab)(abab)(abab)
-Nope(ababababababab)(ababababab)
-Nope(ababababababababab)(abab)
-Nope(ababababababababababababab)(abab)(abab)
-Nope(ababababababababababababababababab)(abab)(abab)(abab)
-Nope-Nope
(abababababab)(ab)(abab)(ab)
-Nope(abababababab)(ab)(abab)
-Nope(ababababababababab)(ab)(ab)(ab)
-Nope(abababababababababababababab)(ababababababab)
-Nope-Nope
(abababababab)(ababab)(ab)(ab)
-Nope(abababababab)(abab)(ab)
-Nope(abababababababab)(abab)(abab)(abab)
-Nope(ababababababababababababababab)(ab)(ab)(ab)
-Nope(ababababababababababababababababababab)(abab)(abab)(abab)(abab)
-Nope)
-Nope
(ababababab)(abab)(abab)(abab)(abab)
-Nope(ababababab)(abab)(ab)(ab)(ab)
-Nope(abababababababab)(ab)(ababab)(abab)(abab)(abab)(abab)
-Nope(abababababababababababababab)(abab)(abab)(abab)(abab)(abab)(abab)
-Nope
(ab)
-不
可能的组合数量随着输入的长度呈指数级增长,在您知道之前,正则表达式引擎正在消耗您的所有系统资源,试图解决这个问题,直到用尽所有可能的术语组合,它最终放弃并报告“没有匹配项”与此同时,你的服务器变成了一堆熔化的金属。
这其实很棘手。现代正则表达式引擎中的灾难性回溯本质上类似于艾伦·图灵证明不可能解决的停止问题。我自己也写过有问题的正则表达式,尽管我知道它们是什么,并且通常知道如何避免它们。在一个原子组中包装所有可以包装的东西有助于防止回溯问题。它基本上告诉正则表达式引擎不要重新访问给定的表达式——“锁定第一次尝试匹配的内容”。但是,请注意,原子表达式不会阻止表达式内的回溯,因此
^(?)?
不幸的是,一旦编写完成,实际上很难立即或快速找到问题正则表达式。最后,识别一个错误的正则表达式就像识别任何其他错误代码一样——它需要大量的时间和经验和/或单个灾难性事件。
有趣的是,因为这个答案是第一次写成的,得克萨斯大学奥斯汀分校的一个小组发表了一篇论文,描述了一个工具,它能够对正则表达式进行静态分析,明确的目的是找到这些“邪恶”模式。该工具是为分析Java程序而开发的,但我怀疑在未来几年中,我们将看到更多的工具围绕分析和检测JavaScript和其他语言中有问题的模式而开发,特别是在重做攻击率不断攀升的情况下。
使用正则表达式程序损坏DoS漏洞的静态检测[BR>瓦伦丁W·Suthoz,Oswaldo Olivo,Mijjn J.Heule,Isil Dillig Br>得克萨斯大学奥斯汀分校
问题内容: 一个ajax请求返回一个标准的JSON数组,其中填充了用户的输入。输入已经过清理,使用eval()函数,我可以轻松创建javascript对象并更新页面。 这就是问题所在。无论我多么努力清理输入,我都不想使用eval()函数。我已经检查了谷歌的方法来使用“没有eval的AJAX中的JSON”,并且遇到了很多不同的方法… 我应该使用哪一个?有没有一种标准的,经过验证的安全方法来做到这一点
正则获取指定字符到下一个大写字符之间的内容
Lua 是所有脚本语言中最快、最简洁的,我们爱她的快、她的简洁,但是我们也不得不忍受因为这些快、简洁最后带来的一些弊端,我们来挨个数数 module 有多少“邪恶”的吧。 由于 lua_code_cache off 情况下,缓存的代码会伴随请求完结而释放。module 的最大好处缓存这时候是无法发挥的,所以本章的内容都是基于 lua_code_cache on 的情况下。 先看看下面代码: loc
当前情况暂且可以满足: 但若: 头)被截断了。如何修改呢? 字符串的格式:\d+\.(我希望这里是任意字符,但也可以削减范围)+ * 然后重复。
7.2 邪恶的代码 现在让我们本着学以致用的目的,用注入搞点好玩的东西。我们将创造一个后门程序, 将它命名为一个系统中正规的程序(比如 calc.exe)。只要用户执行了 calc.exe,我们的后门 就能获得系统的控制权。cacl.exe 执行后,就会在执行后门代码的同时,执行原先的 calc.exe (之前我们的后门命名成 calc.exe,将原来的 cacl.exe 移到别的地方)。当 ca
我有3个正则表达式,但当模式匹配时执行相同的操作,所以我考虑将所有三个表达式合并为一个。我尝试了很多,但无法让“|”I.e”或“在我的正则表达式中工作 regex1:<代码>文本。替换(/([\u00A9-\u3299])/g,函数myFunction(x){…} regex2: regex3: 我试过这样做,但它不起作用regex: