Опасность объединения суперглобальных массивов

Иногда разработчики для удобства используют объединение суперглобальных массивов в один, например:

$input = array_merge($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, $_ENV, (array) @ $_SESSION);

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

Ещё большую опасность данный метод проявляет при загрузке файлов. Не все знают, что стандартными методами POST и GET на сервер можно отправлять полноценные ассоциативные массивы (в том числе многоуровневые). В частности, вот такая HTML-форма:

<form method="post">
    <input type="text" name="file[name]" value="Похищаемый .htaccess">
    <input type="text" name="file[error]" value="0">
    <input type="text" name="file[tmp_name]" value=".htaccess">
</form>

...при отправке на сервер сымитирует описание загруженного файла file из массива $_FILES (приведены только наиболее часто используемые ключи). Причём "файл" будет помечен успешно загруженным. Если обработчик формы использует итоговый объединённый массив, включающий массивы $_POST и $_FILES (в любом порядке), достаточно не отправлять никаких файлов и в форме указать интересующий файл на целевом сервере — сервер скорее всего не распознает подделку. Что именно произойдёт с этим "загруженным файлом" — зависит от исполняемого PHP-скрипта. Может быть, сбой обработки, а может быть — вывод на экран пользователя. Кстати, можно пробовать указывать и удалённые файлы...

В целом, данный приём (объединение суперглобальных массивов) встречается нечасто и, как правило, не ведёт к уязвимости. Тем обиднее обнаружить, что данная уязвимость имела место и была использована эрудированным злоумышленником. Помните об этом и получайте информацию о загруженных файлах только из массива $_FILES, и одной потенциальной проблемой у вас будет меньше.

Записи