2014-02-18 3 views
13

Я хотел бы предоставить небольшие пользовательские регулярные выражения для отправки на тестирование. Тем не менее, есть много проблем, которые следует учитывать при использовании неиспользуемого сервера для более злого использования eval().PHP - Является ли это безопасным способом предоставления пользовательских регулярных выражений

Насколько я знаю, я рассмотрел все проблемы, о которых я мог думать в следующем коде. Являются ли их любые векторы атаки, о которых я не думал? (Довольно наивный вопрос, который я знаю)

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')); 
+0

'if (strpos ($ regex, 0)! == false && trim ($ regex)) {return false; } 'наверху было бы легче понять :) –

+0

Спасибо, я обновил его. Также обратите внимание, что 'chr (0)! == 0' – Xeoncross

+0

А, проверьте документацию, и вы увидите, что второй аргумент [' strpos() '] (http://php.net/strpos) может быть целочисленное значение :) –

ответ

8

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

Добавленная защита нулевых байт на самом деле не нужно поскольку 5,4, потому что уже есть чеки, сделанные в the leader, the middle и the ending. Последнее, в частности, является относительно недавним commit (2011) для исправления this bug.

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

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

+0

Нуль-байтовая защита на самом деле необходима. для нулевых байтов до конечного разделителя. – Xeoncross

+0

@Xeoncross Спасибо, я обновил свой ответ соответственно; мы оба были правы :) –

1

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

Смежные вопросы