Fastcgi pass, безопасность при использовании nginx и fastcgi

Передача всех без исключения клиентских запросов FastCGI не только нежелательна, но и опасна поскольку может привести к выполнению на сервере стороннего (часто вредоносного)  кода.

 

 

Проверка запросов до их передачи приложению

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

 

Существует несколько решений, выбор следует делать в зависимости от используемой конфигурации системы и от того работают ли Nginx и менеджер процессов FastCGI на одном сервере или же на разных.

 

 

Основное правило — не позволять передавать менеджеру процессов все пользовательские запросы. Для злоумышленника не представляет особого труда передать исполняемый скрипт на уязвимый сервер замаскировав его, например, под изображение.

 

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

 

В спецификации CGI говорится, что файлы, содержащие после «/» дополнительную информацию могут  выполняться как скрипты. Это позволяет злоумышленнику сформировать URI так, что «дополнительной информации» будет предшествовать некий файл, как скрипт не выглядящий, который фактически им будет являться.

 

Пример:

/test.jpg/index.php

 

Если конфигурация сервера позволяет выполнять все файлы с расширением .php без проверки FastCGI попытается выполнить переданный запрос. index.php будет расценен как дополнительная информация, test.jpg будет выполнен.

 

Файл при этом может не быть изображением фактически. Здесь основная угроза.

 

Самый простой выход из ситуации — выключить возможность использования добавочных путей в настройках РНР.

mcedit /etc/php5/fpm/php.ini

 

Находим опцию cgi.fix_pathinfo, раскомментируем и устанавливаем ее значение равным  «0»

gi.fix_pathinfo=0

 

После этого перезапускаем PHP-FPM

/etc/init.d/php5-fpm restart

 

Описанная ранее ситуация теперь станет невозможна, если файл index.php не существует менеджер процессов вернет ошибку не предпринимая попыток выполнить test.jpg.

 

 

Если FastCGI и Nginx работают на одной машине:

Вместо того, чтобы использовать предыдущий вариант можно проверять существует ли файл index.php, если его нет — выдавать ошибку.

 

В конфиге Nginx реализация решения выглядит так:

location~ \.php$ {

try_files $uri = 404;

    . . .

}

 

 

Если в приложении задана необходимость обрабатывать подобные запросы обрабатывать их нужно, но необходимо производить проверку до передачи бэкенду.

 

Делается это также в конфиге фронтэнд сервера — например, задается директория в которую пользователи могут загружать файлы — и для нее указывается запрет на передачу запросов на бэкенд. Такой способ очень эффективен и при этом позволяет обеспечить безопасность для приложений, для которых неприменимы способы описанные ранее

 

location ^~ /uploads {

}

 

Внутри каталога можно запретить выполнение PHP файлов:

 

location ^~ /uploads {

location~* \.php$ { return 403; }

}

 

РНР скрипты, загруженные в uploads, при попытке передачи на бэкенд будут возвращать ошибку 403.

 

 

Nginx Fastcgi pass и безопасность при передаче запросов

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

 

Это можно реализовать так:

location ~ [^/]\.php(/|$) {

fastcgi_split_path_info ^(.+?\.php)(.*)$;

set $orig_path $fastcgi_path_info;

try_files $fastcgi_script_name = 404;

fastcgi_pass unix:/var/run/php5-fpm.sock;

fastcgi_index index.php;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $request_filename;

fastcgi_param PATH_INFO $orig_path;

fastcgi_param PATH_TRANSLATED $document_root $orig_path;

}

 

В nginx fastcgi pass отвечает за проксирование запросов — в данном случае в FPM, за счет fastcgi_split_path_info запрос разделяется.

Путь здесь разделяется на $orig_path и $fastcgi_path_info, также за счет try_files файлы проверяются на существование.

 

Чтобы это работало в конфигурации PHP значение  cgi.fix_pathinfo должно быть установлено в «1».

 

Также для правильной работы приведенного фрагмента конифга в php-fpm.conf следует задать запрет на использование  security.limit_extensions.

 

Наименее безопасный способ выполнять серверные скрипты через Apache — запуская их в режиме CGI, опасность вызвана тем, что скрипты требуют права на исполнения. Тем не менее, если скрипты хорошо написаны или работают в изолированном окружении — это самый простой способ.