13

我想允许提交小的用户定义的正则表达式进行测试。但是,从失控的服务器使用到更邪恶的使用,有许多问题需要考虑eval()

据我所知,我已经处理了以下代码中我能想到的所有问题。他们有我没有想到的攻击媒介吗?(我知道一个相当幼稚的问题)

function testRegex($regex)
{
    // null character allows a premature regex end and "/../e" injection
    if (strpos($regex, 0) !== false || ! trim($regex)) {
        return false;
    }

    $backtrack_limit = ini_set('pcre.backtrack_limit', 200);
    $recursion_limit = ini_set('pcre.recursion_limit', 20);

    $valid = @preg_match("~$regex~u", null) !== false;

    ini_set('pcre.backtrack_limit', $backtrack_limit);
    ini_set('pcre.recursion_limit', $recursion_limit);

    return $valid;
}


$regexes = array(
    "InvalidRegular)Expression",
    '',
    '\w+',
    '\/\w+/',
    'foo[bar]*',
    '\/\x00known/e' . chr(0x00) . chr(0),
    'known~e' . chr(0),
    'known~e' . chr(0x00),
    '[a-z]+',
    '\p{Lu}+',
);


foreach($regexes as $regex) {
    var_dump($regex, testRegex($regex));
}

如果你想看一个null-byte注入的例子:

$user_regex = '.+~e' . chr(0);
$user_match = 'system("whoami")';

var_dump(preg_replace("~$user_regex~u", $user_match, 'foo'));
4

2 回答 2

8

显然,测试字符串是否是有效正则表达式的唯一方法是编译它(当您调用任何匹配函数时完成),因此您所做的事情很有意义。

从 5.4 开始,您添加的空字节保护实际上是不必要的,因为已经在leadermiddleending中进行了检查。后者尤其是一个相对较新的提交(2011 年)来修复这个错误

设置较低的回溯和递归限制是一个足够好的沙箱,也许您也可以检查最大长度。

也就是说,这个特定的解决方案不提供使用修饰符的能力,例如/s,/i/m; 也许这不是您目前主要关心的问题,而是值得深思的:)

于 2014-02-18T02:20:07.747 回答
1

您可以告诉他们输入类似 {expression} 的内容,然后使用 preg_replace()。这样,他们只使用你让他们使用的东西。

于 2014-03-09T14:00:43.613 回答