PHP: обработчик запросов
особенность обработчика запросов в PHP
Мы знаем, что PHP конвертирует запрос в ассоциативный массив в составе суперглобальных переменных $_GET или $_POST. Например, ?foo=bar превращается в array([foo] => ‘bar’). Во время парсинга, обработчик удаляет или заменяет в строке запроса некоторые символы имен аргументов на нижнее подчеркивание. Так, ?%20news[id%00=42 конвертируется в array([news_id] => 42). И, если IDS/IPS или WAF блокируют или логируют нечисловые значения параметра news_id, защиту можно обойти, злоупотребив особенностями парсинга. Например, для:
/test.php?%20news_id%00=dwq
значение аргумента, переданного в параметре %20news[id%00 будет сохранено для элемента массива $_GET[“news_id”].
Почему так происходит?
PHP должен преобразовать все аргументы в переменные с валидными именами, поэтому при обработке строки запроса происходят две вещи:
- удаляются начальные пробелы,
- некоторые символы и пробелы конвертируются в нижние подчеркивания.
Например:
- аргумент %20foo_bar%00 декодируется как foo_bar, имя PHP-переменной после преобразования foo_bar,
- аргумент foo%20bar%00 декодируется как foo bar, имя PHP-переменной после преобразования foo_bar,
- аргумент foo%5bbar%00 декодируется как foo[bar, имя PHP-переменной после преобразования foo_bar.
С помощью простого цикла, размещенного ниже, с помощью функции parse_str можно определить, какие символы были удалены или преобразованы в нижнее подчеркивание:
<?php
$check = "foo{chr}bar";
for($i= 0; $i<= 255;$i++){
parse_str(str_replace("{chr}",chr($i),$check)."=bla",$hasil);
if(isset($hasil['foo_bar'])){
echo "-> ( ".chr($i)." )";
echo "\n";
}
}
?>
Функция parse_str работает над get, post и cookie, таким образом можно установить, какие символы преобразуются в нижнее подчеркивание при обработке строки запроса в PHP.
Вот этот список:
- chr(32) ( ) (пробел),
- chr(46) (.) (точка),
- chr(91) ([) (открывающая квадратная скобка),
- chr(128) — chr(159) (различные символы).
Спасибо за внимание.
Перевод статьи “PHP query string parser vulnerability”.