
Затронутые версии: Nginx 0.8.41 – 1.4.3 / 1.5.0 – 1.5.7
Ссылки:
Эта уязвимость не имеет прямого отношения к выполнению кода. Основная причина — некорректный разбор URI запроса, из-за которого ошибочно определяется имя запрашиваемого пользователем файла, что приводит к обходу прав доступа и, как следствие, к выполнению кода.
Например, если Nginx сопоставляет запрос, оканчивающийся на .php, и отправляет его на обработку в fastcgi, типичная конфигурация выглядит так:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /var/www/html;
}
В обычных условиях (при отключённом pathinfo) только файлы с расширением .php отправляются на обработку в fastcgi.
Однако при наличии CVE-2013-4547, если запросить 1.gif[0x20][0x00].php, этот URI соответствует регулярному выражению \.php$ и попадает в данный блок location. Но после этого Nginx ошибочно считает, что запрашиваемый файл — это 1.gif[0x20], и устанавливает его как значение SCRIPT_FILENAME, отправляя в fastcgi.
fastcgi обрабатывает файл на основе значения SCRIPT_FILENAME, что в итоге приводит к уязвимости парсинга.
Таким образом, достаточно загрузить файл с пробелом в конце имени, чтобы PHP обработал его.
Ещё один пример: многие сайты ограничивают IP-адреса, с которых разрешён доступ к административной панели:
location /admin/ {
allow 127.0.0.1;
deny all;
}
Мы можем запросить следующий URI: /test[0x20]/../admin/index.php. Этот URI не совпадает с /admin/ из location, поэтому проверка IP обходится. Однако в итоге запрашивается файл /test[0x20]/../admin/index.php, то есть /admin/index.php, и доступ к административной панели успешно получается. (Здесь нужно, чтобы существовала директория test — это особенность Linux: если директории не существует, то даже при переходе на уровень выше возникнет ошибка «файл не найден»; в Windows такого ограничения нет.)
Запустите окружение с уязвимостью:
docker-compose build
docker-compose up -d
После запуска окружения откройте http://your-ip:8080/ — вы увидите страницу загрузки файлов.
В этом окружении используется проверка по чёрному списку, поэтому мы не можем загрузить файл с расширением .php — нужно использовать CVE-2013-4547. Загрузим файл 1.gif , обратите внимание на пробел в конце:

Откройте http://your-ip:8080/uploadfiles/1.gif[0x20][0x00].php — можно заметить, что PHP выполнился:

Обратите внимание: [0x20] — это пробел, а [0x00] — это \0. Оба этих символа не требуют кодирования.