Как настроить Nginx для защиты от атак и уязвимостей
Кошмар каждого системного администратора: сервер парализован, логи заполнены ошибками, кто-то атакует внутреннюю инфраструктуру и выполняет действия от имени пользователя.
Обычно это происходит из-за таких уязвимостей, как RCE (удаленное исполнение кода), SSRF (подделка запросов на стороне сервера) и CSRF (межсайтовая подделка запроса).
И такие атаки – не редкость.
По данным центра исследования киберугроз Solar 4RAYS, во втором квартале 2025 года число обнаруженных уязвимостей в популярных веб-приложениях выросло на 58% по сравнению с предыдущим кварталом, а решения “Лаборатории Касперского” ежедневно обнаруживают 500 тыс. новых вредоносных файлов.
Чтобы избежать атак или как минимум сократить последствия, важно грамотно настроить сервер.
В этой статье разбираем, как можно снизить угрозу уязвимостей и атак на Nginx – самый популярный веб-сервер в мире.
Итак, вот наш топ рекомендаций для защиты Nginx.
Проверьте файлы, доступные публично
При типовой конфигурации для работы с PHP конфигурация выглядит так:
Директива try _files выполняется слева направо, то есть при запросе сначала проверяется доступность файла из запроса – и, при его наличии, он будет отдан. Это базовый функционал веб-сервера, но таким образом можно извне прочитать различные файлы конфигурации в папке приложения, файлы версий Composer, .bak, .sql и т. д., о которых разработчик не задумывается.При использовании Composer, кроме доступа к файлам версий, при неверной конфигурации существует возможность запуска PHP-файлов зависимостей из папки “vendor” напрямую. Иногда зависимости содержат файлы примеров, скриптов или различных модулей, не задействованных в основном приложении, с помощью которых возможно исполнение кода или отображение произвольного текста, открывающее возможность для проведения CSRF-атак.Внимательно относитесь к файлам, которые становятся доступны публично, – храните приватные данные вне web-root, отключайте листинг директорий и явно ограничивайте доступ к чувствительным типам файлов через deny all или точные правила try_files.
Переменные в proxy_pass
proxy_pass используется для перенаправления запросов с веб-сервера на другой сервер и указывает на путь или URL, на который проксируется запрос, полученный Nginx.
Мы рекомендуем быть аккуратными с использованием переменных в proxy_pass, поскольку если на их содержимое может влиять злоумышленник (например, как в примере выше, когда содержимое $http_host и $request_uri берется из HTTP-запроса), это дает возможность организовать атаку типа SSRF – отправлять запросы внутренним сервисам.
Грамотным решением может стать исключение использования непроверенных переменных в proxy_pass. Если есть возможность, вместо подстановки $http_host задавайте фиксированный целевой адрес или применяйте строгую валидацию и маппинг допустимых хостов.
Будьте осторожны со слешами
При лишних слешах можно вставить “..” – и получить доступ туда, куда разработчик приложения не предполагал предоставлять доступ.
При такой конфигурации:
location /static {
alias /home/app/static/;
}
Если мы выполним запрос:
GET /static../settings.py
Сервер Nginx достаточно прямолинейно обработает запрос и добавит‘../settings.py’к значению директивы alias:
/home/app/static/../settings.py
Таким образом можно получить доступ за пределы ожидаемой разработчиком папки.
Так же это работает и с другими директивами, такими как proxy_pass:
Так можно выйти за пределы ожидаемого сегмента адреса (v1 в нашем случае). Например, если в качестве проксируемого сервера используется Apache, то данным запросом можно раскрыть его статусную страницу.
Старайтесь использовать root вместо alias, если структура приложения позволяет, и валидируйте пути на стороне проксируемого сервера.
Будьте аккуратны с FastCGI
Когда Nginx передает запросы с помощью протокола FastCGI, каждое сообщение FastCGI содержит набор переменных среды. Поэтому настройка Nginx должна включать проверку, какие переменные среды передаются через директивы fastcgi_param, – чтобы избежать исполнения кода или раскрытия данных, не предусмотренных разработчиком.
Для URL, оканчивающихся на .php, Nginx не будет проверять существование файла и слепо передаст в переменной SCRIPT_FILENAME нормализованный путь из запроса. В зависимости от типа и версии вашего FastCGI-бэкенда, типа операционной системы, используемой локали, файловой системы, а также конфигурации самого Nginx, существуют различные способы манипуляций с адресом для исполнения кода, не предусмотренного разработчиком.
Переменная SCRIPT_FILENAME будет доступна в PHP $_SERVER[‘SCRIPT_NAME’]. Если она или ее производные выводятся на страницу без экранирования, то злоумышленник может вставить в адресную строку вредоносный код, который отобразится на странице в оригинальном виде.
Так же, например, можно вставить пробел, слеш, null-символ или другие спецсимволы в адрес, чтобы FastCGI-бэкенд исполнил не тот файл, который указан в адресе.
Классический пример:
GET /upload/avatar.jpg/.php
Nginx передаст этот запрос FastCGI-бэкенду, а код из avatar.jpg может быть исполнен как скрипт (или, в зависимости от бэкенда, отдан как текст).
В современном PHP-FPM директива security.limit_extensions содержит список допустимых расширений файлов для исполнения и должна предотвратить конкретно этот сценарий, но нужно быть аккуратными с другими FastCGI-бэкендами, а также при более пермиссивной настройке security.limit_extensions (например, часто туда добавляют .inc).
Чтобы не передавать лишние запросы, можно проверять наличие файлов в самом Nginx:
{
try_files $uri =404;
fastcgi_pass …;
}
Будьте осторожны с переменными
$uri и $document_uri – это нормализованные переменные, то есть последовательность вида %0d%0a декодируется в реальные символы переноса строки (CRLF).
Таким образом в подобной конфигурации можно вставить неожиданный перенос строки и дописать свои заголовки:
HTTP/1.1 302 Moved Temporarily
...
Location: http://172.17.0.1/static/
X-Foo: CRLF
Для защиты от подобных CSRF в Nginx важно тщательно управлять заголовками, которые могут быть применены злоумышленниками, использовать безопасные переменные вроде $request_uri, а также merge_slashes on – чтобы исключить обход правил через манипуляции с URL.
Конфигурация SSL должна быть надежной
Мы рекомендуем не играть в криптографа и использовать надежные средства для конфигурации SSL – например, Mozilla SSL Configuration Generator. Так можно предотвратить MITM-атаки, при которых злоумышленник перехватывает и потенциально изменяет коммуникацию между сторонами, что позволяет ему просматривать содержимое всех передаваемых ими сообщений, удалять и изменять их.
Заключение
Любые атаки – серьезная угроза для сайтов и приложений, а защита от них требует комплексного подхода. В этой статье мы разобрали неочевидные нюансы, которые стоит учесть при настройке Nginx, при этом для защиты VPS-сервера могут быть полезны и другие способы.
Например, если ваша инфраструктура находится в облаке, можно использовать CDN– сеть доставки контента, которая обеспечит дополнительную защиту от атак благодаря переводу запросов к контенту на серверы CDN.
Если у вас возникли вопросы, свяжитесь с нами удобным для вас способом – и мы обязательно ответим. Также ждем вас в нашем официальном Telegram-канале, а пообщаться на любую тему с коллегами по цеху и сотрудниками Beget вы можете в нашем чате.