有什么方法可以将恶意代码放入正则表达式中?


138

我想在我的公共网页上添加正则表达式搜索功能。除了对输出进行HTML编码之外,我还需要采取其他措施来防止恶意用户输入吗?

解决正反问题的人们淹没了Google搜索-使用正则表达式检测恶意输入-我对此并不感兴趣。在我的情况下,用户输入一个正则表达式。

我将在.NET(C#)中使用Regex库。


4
这可能取决于您使用的语言和/或正则表达式库。
aschepler,2011年

一些更多的阅读材料:在OWASP重做操作重做操作维基百科
joeytwiddle

Answers:


216

拒绝服务顾虑

正则表达式最常见的问题是通过呈指数级甚至超指数级的病理模式进行的拒绝服务攻击!—因此似乎需要永远解决。这些可能只显示在特定的输入数据上,但是通常可以创建一个无关紧要的数据。

这些是哪一种将在某种程度上取决于您所使用的regex编译器的智能程度,因为其中有些可以在编译时检测到。实现递归的正则表达式编译器通常具有内置的递归深度计数器,用于检查非递归。

拉斯·考克斯(Russ Cox)在2007年出色的关于正则表达式匹配的论文可以既简单又快速(但是在Java,Perl,PHP,Python,Ruby等方面却很慢)谈论了大多数现代NFA的方式,这些似乎都源于Henry Spencer的代码会遭受严重的性能下降,但是汤普森(Thompson)风格的NFA没有此类问题。

如果您只接受DFA可以解决的模式,则可以将其编译成这样,它们将运行得更快,甚至可能更快。但是,这需要时间。Cox论文提到了这种方法及其附带的问题。一切都归结为经典的时空权衡。

使用DFA,您将花费更多的时间来构建它(并分配更多的状态),而使用NFA时,您将花费更多的时间来执行它,因为它可以同时处于多个状态,并且回溯可以吃掉您的午餐和CPU。

拒绝服务解决方案

解决这些模式的最合理的方法可能是在竞赛中随着宇宙的热死而逐渐消失,这是用计时器包装它们,该计时器可以有效地放置执行它们所允许的最大时间。通常,这将比大多数HTTP服务器提供的默认超时小很多。

有多种方法可以实现这些功能,从alarm(N)C级的简单形式到某种try {}类型的catch警报类型的异常阻止,一直到产生一个新线程,该线程是专门建立在其中的具有时间限制的。

代码标注

在允许代码标注的正则表达式语言中,提供一些机制来允许或禁止您要编译的字符串中的代码标注。即使代码标注仅用于使用您所使用的语言编写代码,也应限制它们;他们不必调用外部代码,尽管如果可以,您将遇到更大的问题。

例如,在Perl中,除非use re "eval";在当前作用域中处于活动状态的特殊的词法范围编译指示有效,否则不能在通过字符串插值创建的正则表达式中使用代码标注(因为这样,因为它们是在运行时编译的)。

这样,没有人可以潜入代码标注来运行诸如之类的系统程序rm -rf *。由于代码标注对安全性非常敏感,因此默认情况下,Perl会在所有插值字符串上将其禁用,并且您必须竭尽全力来重新启用它们。

用户定义的\ P {roperties}

仍然与Unicode的样式属性一个更安全的敏感问题-像\pM\p{Pd}\p{Pattern_Syntax},或者\p{Script=Greek}-这可能会存在一些正则表达式的编译器支持该符号。

问题在于,其中某些属性集是用户可扩展的。这意味着您可以拥有自定义属性,这些属性是对某些特定名称空间(例如\p{GoodChars}或)中命名函数的实际代码标注\p{Class::Good_Characters}。您的语言如何处理这些问题可能值得研究。

沙盒

在Perl中,通过Safe模块的沙盒隔离区将控制名称空间的可见性。其他语言也提供类似的沙盒技术。如果有可用的此类设备,则可能需要对其进行研究,因为它们是专门为有限执行不受信任的代码而设计的。


4
NFA-> DFA转换可以产生指数状态爆炸,将时间DoS转换为空间DoS,以及产生指数状态数的时间成本。
巴里·凯利

但可能他不需要整个正则表达式功能,您如何看待像google这样限制正则表达式的功能呢?google.com/intl/zh-CN/help/faq_codesearch.html#regexp
systemsfault 2011年

1
@Barry完全正确。我一直在考虑拉斯·考克斯(Russ Cox)在他的一篇论文中描述的策略,该策略将NFA的各个部分逐步编译为等效的DFA,但如果太大则将其丢弃。但是即使Thompson证明了它等同于NFA,DFA中也没有万灵药,因为您确实必须在某个时候或其他时候向吹笛者付款。向操作系统请求更多空间所花费的时间,以及随之而来的页表设置成本,有时可能以另一种方式进一步推算平衡规模,并使从时间到空间的转换吸引力降低。
tchrist 2011年

20

添加到tchrist的出色答案中:编写“正则表达式”页面的同一Russ Cox也发布了代码!re2是一个C ++库,可确保O(length_of_regex)运行时和可配置的内存使用限制。它在Google中使用,因此您可以在Google代码搜索中输入正则表达式-这意味着它已经过实战测试。


2
的确如此。您可以使用模块将re2交换到Perl的regex引擎中,如果可能,它将使用re2,否则将使用Perl。效果很好。
tchrist 2011年


6

您需要阅读以下文章:

不安全的上下文切换:接种正则表达式以提高生存能力 本文更多地讨论了正则表达式引擎(例如PCRE)可能出现的问题,但它可以帮助您了解要面对的问题。


1
这是有关GNU libc regcomp(3)代码的安全建议:securityreason.com/achievement_securityalert/93 多及时!至少在linux下,该漏洞很容易证明:grep -E“。* {10,} {10,} {10,} {10,} {10,}”
Bruce Ediger

5

您不仅要担心匹配本身,而且还要担心如何进行匹配。例如,如果您的输入在进入正则表达式引擎的过程中经历了某种评估阶段或命令替换,则可能在模式内部执行了代码。或者,如果您的正则表达式语法允许使用嵌入式命令,则也必须注意这一点。由于您没有在问题中指定语言,因此很难确定所有安全含义是什么。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.