Кошмар каждого системного администратора: сервер парализован, логи заполнены ошибками, кто-то атакует внутреннюю инфраструктуру и выполняет действия от имени пользователя.
Обычно это происходит из-за таких уязвимостей, как RCE (удаленное исполнение кода), SSRF (подделка запросов на стороне сервера) и CSRF (межсайтовая подделка запроса).
И такие атаки — не редкость.
Кошмар каждого системного администратора: сервер парализован, логи заполнены ошибками, кто-то атакует внутреннюю инфраструктуру и выполняет действия от имени пользователя.
Обычно это происходит из-за таких уязвимостей, как 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 используется для перенаправления запросов с веб-сервера на другой сервер и указывает на путь или URL, на который проксируется запрос, полученный Nginx.
Рассмотрим такую конфигурацию:
Мы рекомендуем быть аккуратными с использованием переменных в proxy_pass, поскольку если на их содержимое может влиять злоумышленник (например, как в примере выше, когда содержимое $http_host и $request_uri берется из HTTP-запроса), это дает возможность организовать атаку типа SSRF — отправлять запросы внутренним сервисам.
Грамотным решением может стать исключение использования непроверенных переменных в proxy_pass. Если есть возможность, вместо подстановки $http_host задавайте фиксированный целевой адрес или применяйте строгую валидацию и маппинг допустимых хостов.
При лишних слешах можно вставить «..» — и получить доступ туда, куда разработчик приложения не предполагал предоставлять доступ.
При такой конфигурации:
Если мы выполним запрос:
Сервер Nginx достаточно прямолинейно обработает запрос и добавит ‘../settings.py’ к значению директивы alias:
Таким образом можно получить доступ за пределы ожидаемой разработчиком папки.
Так же это работает и с другими директивами, такими как proxy_pass:
Так можно выйти за пределы ожидаемого сегмента адреса (v1 в нашем случае). Например, если в качестве проксируемого сервера используется Apache, то данным запросом можно раскрыть его статусную страницу.
Apache получит запрос: http://apiserver/v1/../server-status
Старайтесь использовать root вместо alias, если структура приложения позволяет, и валидируйте пути на стороне проксируемого сервера.
Когда Nginx передает запросы с помощью протокола FastCGI, каждое сообщение FastCGI содержит набор переменных среды. Поэтому настройка Nginx должна включать проверку, какие переменные среды передаются через директивы fastcgi_param, — чтобы избежать исполнения кода или раскрытия данных, не предусмотренных разработчиком.
Например, безобидная конфигурация:
Для URL, оканчивающихся на .php, Nginx не будет проверять существование файла и слепо передаст в переменной SCRIPT_FILENAME нормализованный путь из запроса. В зависимости от типа и версии вашего FastCGI-бэкенда, типа операционной системы, используемой локали, файловой системы, а также конфигурации самого Nginx, существуют различные способы манипуляций с адресом для исполнения кода, не предусмотренного разработчиком.
Переменная SCRIPT_FILENAME будет доступна в PHP $_SERVER[’SCRIPT_NAME’]. Если она или ее производные выводятся на страницу без экранирования, то злоумышленник может вставить в адресную строку вредоносный код, который отобразится на странице в оригинальном виде.
Так же, например, можно вставить пробел, слеш, null-символ или другие спецсимволы в адрес, чтобы FastCGI-бэкенд исполнил не тот файл, который указан в адресе.
Классический пример:
Nginx передаст этот запрос FastCGI-бэкенду, а код из avatar.jpg может быть исполнен как скрипт (или, в зависимости от бэкенда, отдан как текст).
В современном PHP-FPM директива security.limit_extensions содержит список допустимых расширений файлов для исполнения и должна предотвратить конкретно этот сценарий, но нужно быть аккуратными с другими FastCGI-бэкендами, а также при более пермиссивной настройке security.limit_extensions (например, часто туда добавляют .inc).
Чтобы не передавать лишние запросы, можно проверять наличие файлов в самом Nginx:
$uri и $document_uri — это нормализованные переменные, то есть последовательность вида %0d%0a декодируется в реальные символы переноса строки (CRLF).
Таким образом в подобной конфигурации можно вставить неожиданный перенос строки и дописать свои заголовки:
Nginx вернет:
Для защиты от подобных CSRF в Nginx важно тщательно управлять заголовками, которые могут быть применены злоумышленниками, использовать безопасные переменные вроде $request_uri, а также merge_slashes on — чтобы исключить обход правил через манипуляции с URL.
Мы рекомендуем не играть в криптографа и использовать надежные средства для конфигурации SSL — например, Mozilla SSL Configuration Generator.
Так можно предотвратить MITM-атаки, при которых злоумышленник перехватывает и потенциально изменяет коммуникацию между сторонами, что позволяет ему просматривать содержимое всех передаваемых ими сообщений, удалять и изменять их.
Любые атаки — серьезная угроза для сайтов и приложений, а защита от них требует комплексного подхода. В этой статье мы разобрали неочевидные нюансы, которые стоит учесть при настройке Nginx, при этом для защиты VPS-сервера могут быть полезны и другие способы.
Например, если ваша инфраструктура находится в облаке, можно использовать CDN — сеть доставки контента, которая обеспечит дополнительную защиту от атак благодаря переводу запросов к контенту на серверы CDN.
Если у вас возникли вопросы, свяжитесь с нами удобным для вас способом — и мы обязательно ответим. Также ждем вас в нашем официальном Telegram-канале, а пообщаться на любую тему с коллегами по цеху и сотрудниками Beget вы можете в нашем чате.