Подтвердить что ты не робот

PHP. Является ли это безопасным способом предоставления пользовательских регулярных выражений?

Я хотел бы предоставить небольшие пользовательские регулярные выражения для тестирования. Тем не менее, есть много проблем, которые следует учитывать при использовании автономного сервера для более злого использования 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'));
4b9b3361

Ответ 1

Очевидно, что единственный способ проверить, является ли строка допустимым регулярным выражением, заключается в ее компиляции (что делается при вызове любой из соответствующих функций), поэтому то, что вы делаете, имеет большой смысл.

Нулевая байтовая защита на самом деле не нужна с 5.4, поскольку в лидере уже есть проверки, средний и конец. Последнее, в частности, является относительно недавним commit (2011), чтобы исправить эту ошибку.

Настройка нижнего предела возврата и ограничение рекурсии - достаточно хорошая песочница, возможно, вы также можете проверить максимальную длину.

Тем не менее, это конкретное решение не дает возможности использовать модификаторы, такие как /s, /i и /m; возможно, это не ваша главная забота на данный момент, а скорее пища для размышлений:)

Ответ 2

Вы можете сказать им ввести что-то вроде {выражение}, а затем использовать preg_replace(). Таким образом, они используют только то, что вы им позволяете.