Материал проходит модерацию
Бегет
18.12.2025, 23:30

Как настроить Nginx для защиты от атак и уязвимостей

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

Обычно это происходит из-за таких уязвимостей, как RCE (удаленное исполнение кода), SSRF (подделка запросов на стороне сервера) и CSRF (межсайтовая подделка запроса).

И такие атаки – не редкость.

По данным центра исследования киберугроз Solar 4RAYS, во втором квартале 2025 года число обнаруженных уязвимостей в популярных веб-приложениях выросло на 58% по сравнению с предыдущим кварталом, а решения “Лаборатории Касперского” ежедневно обнаруживают 500 тыс. новых вредоносных файлов.

Чтобы избежать атак или как минимум сократить последствия, важно грамотно настроить сервер.

В этой статье разбираем, как можно снизить угрозу уязвимостей и атак на Nginx – самый популярный веб-сервер в мире.

Итак, вот наш топ рекомендаций для защиты Nginx.

Проверьте файлы, доступные публично

При типовой конфигурации для работы с PHP конфигурация выглядит так:

location / { try_files $uri $uri/ /index.php?$args; }

Директива try _files выполняется слева направо, то есть при запросе сначала проверяется доступность файла из запроса – и, при его наличии, он будет отдан. Это базовый функционал веб-сервера, но таким образом можно извне прочитать различные файлы конфигурации в папке приложения, файлы версий Composer, .bak, .sql и т. д., о которых разработчик не задумывается.При использовании Composer, кроме доступа к файлам версий, при неверной конфигурации существует возможность запуска PHP-файлов зависимостей из папки “vendor” напрямую. Иногда зависимости содержат файлы примеров, скриптов или различных модулей, не задействованных в основном приложении, с помощью которых возможно исполнение кода или отображение произвольного текста, открывающее возможность для проведения CSRF-атак.Внимательно относитесь к файлам, которые становятся доступны публично, – храните приватные данные вне web-root, отключайте листинг директорий и явно ограничивайте доступ к чувствительным типам файлов через deny all или точные правила try_files.  

Переменные в proxy_pass

proxy_pass используется для перенаправления запросов с веб-сервера на другой сервер и указывает на путь или URL, на который проксируется запрос, полученный Nginx.

Рассмотрим такую конфигурацию:

location / { proxy_pass http://$http_host$request_uri; }

Мы рекомендуем быть аккуратными с использованием переменных в 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:

location /api { proxy_pass http://apiserver/v1/; }

Так можно выйти за пределы ожидаемого сегмента адреса (v1 в нашем случае). Например, если в качестве проксируемого сервера используется Apache, то данным запросом можно раскрыть его статусную страницу.

GET /api../server-status

Apache получит запрос: http://apiserver/v1/../server-status

Старайтесь использовать root вместо alias, если структура приложения позволяет, и валидируйте пути на стороне проксируемого сервера.

Будьте аккуратны с FastCGI

Когда Nginx передает запросы с помощью протокола FastCGI, каждое сообщение FastCGI содержит набор переменных среды. Поэтому настройка Nginx должна включать проверку, какие переменные среды передаются через директивы fastcgi_param, – чтобы избежать исполнения кода или раскрытия данных, не предусмотренных разработчиком.

Например, безобидная конфигурация:

location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_pass ...; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; }

Для 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).

Таким образом в подобной конфигурации можно вставить неожиданный перенос строки и дописать свои заголовки:

location /static/ { return 302 http://172.17.0.1$uri; }GET/static/%0d%0aX-Foo:%20CRLF

Nginx вернет:

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 вы можете в нашем чате.  

Вам понравится

Spectrum Marketing
18.12.2025
Advertronic
15.12.2025
ОККАМ
02.12.2025