Сотрудник сегодня сделал мне ставку на то, что он знает способ подачи специально отформатированной строки, которая могла бы пройти следующую проверку регулярных выражений и все еще предоставлять имя файла с расширением .php
или .jsp
или .asp
:
if (preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $var) && preg_match('/\.(asp|jsp|php)$/i', $var) == false)
{
echo "No way you have extension .php or .jsp or .asp after this check.";
}
Как бы я ни старался и обыскал сеть, я не смог найти недостаток, который мог бы сделать такое. Могу ли я что-то забыть? Учитывая, что проблема с "нулевым байтом" устранена, что еще может быть проблемой?
Примечание. Я не подразумеваю, что этот код является полнофункциональным методом проверки расширения файла, может быть недостаток в функции preg_match()
или содержимое файла может быть разного формата, я просто прошу вопрос в терминах самого синтаксиса регулярного выражения.
EDIT - действительный код:
if (isset($_FILES["image"]) && $_FILES["image"]["name"] && preg_match('/\.(jpeg|jpg|gif|png|bmp|jpe)$/i', $_FILES["image"]["name"]) && preg_match('/\.(asp|jsp|php)$/i', $_FILES["image"]["name"]) == false) {
$time = time();
$imgname = $time . "_" . $_FILES["image"]["name"];
$dest = "../uploads/images/";
if (file_exists($dest) == false) {
mkdir($dest);
}
copy($_FILES['image']['tmp_name'], $dest . $imgname);
}else{
echo "Invalid image file";
}
Версия PHP: 5.3.29
EDIT: эпилог
Оказалось, что "уязвимость" присутствует только в Windows. Тем не менее, он сделал именно то, что сказал мне мой коллега, - проверил проверку регулярного выражения и сохранил файл с исполняемым расширением. Следующее было проверено на WampServer 2.2
с PHP 5.3.13
:
Передача следующей строки в проверку регулярного выражения выше test.php:.jpg
(обратите внимание на символ двоеточия ":" в конце желаемого расширения) проверит его, и функция copy()
, кажется, опускает все после символа двоеточия, включая символ сам.
Опять же, это верно только для окон. В linux файл будет написан точно с тем же именем, который передается функции.