用户定义的正则表达式安全问题

时间:2014-01-05 00:48:44

标签: javascript php regex perl

如果我在服务器上使用用户定义的输入字符串运行用户定义的正则表达式,是否存在任何安全问题?我不是要问一种语言,而是任何语言,PHP是我想要了解的主要语言之一。

例如,如果我有以下代码:

<?php

if(isset($_POST['regex'])) {
    preg_match($_POST['regex'], $_POST['match'], $matches);
    var_dump($matches);
}

?>
<form action="" method="post">
<input type="text" name="regex">
<textarea name="match"></textarea>
<input type="submit">
</form>

提供这不是受控环境(即用户不可信),上述代码有哪些风险?如果为其他语言编写类似的代码,这些其他语言是否存在风险?如果是这样,哪些语言包含威胁?

我已经发现了'邪恶的正则表达式',然而,无论我在计算机上尝试什么,它们似乎工作正常,见下文。

PHP

<?php
php > preg_match('/^((ab)*)+$/', 'ababab', $matches);var_dump($matches);
array(3) {
  [0] =>
  string(6) "ababab"
  [1] =>
  string(0) ""
  [2] =>
  string(2) "ab"
}
php > preg_match('/^((ab)*)+$/', 'abababa', $matches);var_dump($matches);
array(0) {
}

的JavaScript

phantomjs> /^((ab)*)+$/g.exec('ababab');
{
   "0": "ababab",
   "1": "ababab",
   "2": "ab",
   "index": 0,
   "input": "ababab"
}
phantomjs> /^((ab)*)+$/g.exec('abababa');
null

这让我相信PHP和JavaScript具有针对邪恶正则表达式的故障安全机制。基于此,我希望其他语言具有相似的功能。

这是正确的假设吗?

最后,对于任何或所有可能有害的语言,有没有办法确保正则表达式不会造成损害?

1 个答案:

答案 0 :(得分:5)

当您使用用户定义的字符串运行用户定义的正则表达式时,用户可以制作灾难性回溯正则表达式,通常使用失败输入导致系统拒绝服务。

使用您的示例^((ab)*)+$,您需要稍长的失败的输入才能使灾难性的回溯生效:"ababababababababababababababababababababababd"

  • 对于PHP版本,对preg_last_error的调用应返回PREG_BACKTRACK_LIMIT_ERROR
  • 对于JS版本,上面的代码不会在Firefox 26中导致灾难性的回溯,浏览器会返回false。在Chrome 31.0.1650.63 m和Internet Explorer 11上,可以观察到灾难性的回溯。

根据语言/库的API,API可以提供限制回溯尝试次数或设置操作超时的选项;强烈建议您设置限制以防止服务器上的DoS。

  • PCRE 默认在1000次回溯尝试后停止,并且可以配置该号码。
  • .NET Regex类附带一个API,用于限制匹配所需的时间。

如果语言没有这么方便的API,强烈建议你实施自己的超时机制来超时执行。

除非正则表达式引擎的规范包含防止灾难性回溯的要求(例如PCRE具有默认回溯限制),否则您不应该依赖于特定实现的行为(如Firefox的情况)如上所述)。