【问题标题】:Sanitization of User-Supplied Regular Expressions in PHP在 PHP 中清理用户提供的正则表达式
【发布时间】:2011-01-23 04:59:37
【问题描述】:

我想创建一个用户可以测试正则表达式的网站(已经有很多...例如这个:http://www.pagecolumn.com/tool/pregtest.htm)。基本上,用户提供一个正则表达式和一些示例文本,然后将正则表达式评估的结果吐回。

我想使用 PHP“preg_*”函数评估服务器端的正则表达式。有没有办法清理提供的正则表达式?我应该关注哪些安全漏洞?

【问题讨论】:

  • 你为什么不用JS呢?这样您就不必清理任何内容,因为它将在客户端执行。
  • 我应该补充一点,除了评估用户提供的示例文本上的正则表达式之外,我还想评估驻留在服务器上的“秘密”字符串上的正则表达式。如果用户不知道字符串是什么,我不知道如何在 JS 中做到这一点。

标签: php regex sanitization


【解决方案1】:

我认为 PHP 本身会检查正则表达式。 这是我制作的示例脚本:

// check for input, and set max size of input
if(@!empty($_POST['regex'])
    && @!empty($_POST['text'])
    && strlen($_POST['regex'])<1000
    && strlen($_POST['text'])<2000
    ){
    // set script timeout in case something goes wrong (SAFE MODE must be OFF)
    $old_time=ini_get('max_execution_time');
    if(!set_time_limit(1)) die('SAFE MODE MUST BE OFF'); // 1 sec is more then enough

    // trim input, it's up to you to do more checks
    $regex=trim($_POST['regex']);
    // don't trim the text, it can be needed
    $input=$_POST['text'];
    // escape slashes
    $regex=preg_replace('/([\\/]+)?//', '\/', $regex);

    // go for the regex
    if(false===$matched=@preg_match('/'.$regex.'/', $input, $matches)){
            // regex was tested, show results
            echo 'Matches: '.$matched.'<br />';
            if($matched>0){
                    echo 'matches: <br />';
                    foreach($matches as $i =>  $match){
                            echo $i.' = '.$match.'<br />';
                }
            }
    }
    // set back original execution time
    set_time_limit($old_time);
}

无论如何,永远不要对用户提交的字符串使用 eval()

此外,您还可以进行一些简单的简约消毒,但这取决于您。 ;)

【讨论】:

  • 您可以使用preg_quote,而不是自己转义正则表达式字符串
  • 您确定设置 max_execution_time 实际上会限制 preg 运行的时间吗?我的印象是 DL 调用总是会完成,而 max_execution_time 只会在 preg 调用返回后 klill php 脚本。这意味着用户仍然很容易通过提供邪恶的表达方式使您的系统陷入困境。
【解决方案2】:

如果您允许preg_replace 的用户提交值确保您不允许e flag!不这样做可能会让恶意用户删除您的整个网站,甚至更糟。

否则,可能发生的最糟糕的事情就是其他答案已经指出的。设置一个较低的脚本超时时间,也许您甚至应该确保该页面每分钟只能被调用 X 次。

【讨论】:

    【解决方案3】:

    我能想到的唯一问题是有人可以通过输入一个错误的正则表达式(即 O(2^n) 或 O(n!) 或其他)来对你进行 DOS,而防止这种情况发生的最简单方法可能是将您的页面超时设置短。

    【讨论】:

    • ...或者限制PREG的回溯级别。
    【解决方案4】:

    如果正则表达式存储在数据库中,您应该使用通常用来转义数据的任何方法,例如准备好的语句。

    否则,我唯一担心的是用户可能会提供恶意正则表达式,因为它可能包含非常复杂的正则表达式,我不确定是否有办法检查。

    一种想法是,您可以通过在 JS 中执行它来使您的正则表达式评估器成为所有客户端,但是 php 的 preg 函数和 JavaScript 正则表达式函数之间存在不一致。

    【讨论】:

      【解决方案5】:

      Afaik 现在在尝试评估用户提供的正则表达式时存在“漏洞”。可能发生的最糟糕的事情是 - 正如 erik 指出的那样 - DOS 攻击或脚本中的致命错误。

      我很害怕告诉你,你将无法(甚至在理论上)能够“清理”所有可能的正则表达式。您能做的最好的事情就是检查词法和/或句法错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 1970-01-01
        • 2011-05-26
        相关资源
        最近更新 更多