ngx_drop_privs: принцип минимальных привилегий в nginx

Забираем у nginx лишние привилегии

 — замечательный web-сервер, но, как и практически любой программный продукт, не свободен от ошибок, временами весьма критических.

Архитектура nginx такова, что обычно имеется один привилегированный процесс (запускаемый от всемогущего root) и один или более рабочих процессов (обычно работающих от имени непривилегированного пользователя). Тем не менее, я видел конфигурации, в которых все процессы nginx работают под привилегированным пользователем. Один из примеров — многопользовательский сервер, Document Root сайтов на котором имеет права вида 0700 (запускать несколько nginx и настраивать проксирование — тоже не лучший выход).

Кроме того, за последние неполные пять лет в nginx найдено 112 ошибок (segmentation fault), некоторые из которых теоретически могут дать возможность выполнения произвольного кода в системе (wget http://sysoev.ru/nginx/changes.html -q -O - | grep segmentation | wc -l).

Я не знаю, все ли ошибки затрагивали только рабочие процессы, либо были ошибки в главном процессе — рисковать не хочется. Так и родилась идея написать модуль для nginx — .

Данный модуль будет работать, скорее всего, только под , при этом для работы требуется наличие библиотеки libcap и ядра, собранного с поддержкой capabilities (я давно не видел ядра без такой поддержки).

Идея заключается в том, что процессу, который порождает потомков, меняет их UID/GID и периодически меняет владельца log-файлов, привилегий root слишком много. Вполне достаточно CAP_SETUID, CAP_SETGID и CAP_CHOWN (если нужна ротация логов).

CAP_CHOWN — весьма опасная возможность, и если есть возможность её не давать, лучше её не давать :-)

Модуль при инициализации проверяет, запущен ли главный процесс от имени root. Если да, то capabilities сбрасываются на указанные в директиве dropprivs_set_caps.

Директива dropprivs_set_caps является глобальной (как, например, daemon, user и pid) и имеет формат

[-]
View Code nginx configuration
dropprivs_set_caps "строка";

где строка — привилегии в формате, который понимает функция cap_from_text(). Никто не говорил, что будет легко.

На своей тестовой машине я использую такое значение:

[-]
View Code nginx configuration
dropprivs_set_caps "cap_setuid,cap_setgid=ep";

Это равносильно сбросу всех привилегий и установке CAP_SETUID и CAP_SETGID в действующем (effective) и разрешённом (permitted) наборе привилегий.

Те, кому это всё интересно, могут скачать исходный код модуля ngx_drop_privs. Код пока ещё сыроват (да, написан за полтора часа этой ночью) и будет совершенствоваться. Любые предложения/патчи are always welcome. Планируется поддержка chroot, что позволит меньше беспокоиться о CAP_CHOWN и CAP_SETUID.

UPDATE 16.02.2010: добавлена экспериментальная поддержка chroot. Реализуется глобальной директивой

[-]
View Code nginx configuration
dropprivs_chroot "каталог";

Выполняется chroot() до сброса привилегий, поэтому явным образом указывать CAP_SYS_CHROOT в списке разрешённых привилегий не нужно (и вообще не рекомендуется). Перед вызовом chroot() выполняется chdir() в указанный каталог, поэтому если привилегии настроены нормально, покинуть chroot демон не сможет. Тем не менее, это накладывает свои ограничения:

  • пути в виртуальных хостах должны быть относительны нового корня;
  • в новом корне должен существовать как минимум /dev/zero;
  • PID-файл создаётся относительно нового корня;
  • что происходит с лог-файлами, пока сказать не могу, но есть подозрение что ротация логов без танцев с бубном работать не будет.

Сборка модуля:

[-]
View Code Bash
cd /path/to/nginx/source
./configure \ # Здесь идут обычные опции configure
    --add-module=/path/to/ngx_drop_privs
make
Автор: ; опубликовано в: C/C++, Linux, nginx, Безопасность; метки: C/C++, Linux, nginx, ngx_drop_privs, безопасность
23
Сен
2009

RSS Комментарии к статье «ngx_drop_privs: принцип минимальных привилегий в nginx» (3)  »

  1. Alex

    не проще ли сам nginx запустить в chroot?

  2. Для тех, кто умеет пользоваться bzr: самая последняя версия кода находится в bzr://bzr.sjinks.pro/ngx_drop_privs/trunk

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

Оставить комментарий к записи «ngx_drop_privs: принцип минимальных привилегий в nginx»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा