ngx_drop_privs: принцип минимальных привилегий в nginx
Забираем у 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 — ngx_drop_privs.
Данный модуль будет работать, скорее всего, только под Linux, при этом для работы требуется наличие библиотеки 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) и имеет формат
где строка — привилегии в формате, который понимает функция cap_from_text(). Никто не говорил, что будет легко.
На своей тестовой машине я использую такое значение:
Это равносильно сбросу всех привилегий и установке CAP_SETUID и CAP_SETGID в действующем (effective) и разрешённом (permitted) наборе привилегий.
Те, кому это всё интересно, могут скачать исходный код модуля ngx_drop_privs. Код пока ещё сыроват (да, написан за полтора часа этой ночью) и будет совершенствоваться. Любые предложения/патчи are always welcome. Планируется поддержка chroot, что позволит меньше беспокоиться о CAP_CHOWN и CAP_SETUID.
UPDATE 16.02.2010: добавлена экспериментальная поддержка chroot. Реализуется глобальной директивой
Выполняется chroot() до сброса привилегий, поэтому явным образом указывать CAP_SYS_CHROOT в списке разрешённых привилегий не нужно (и вообще не рекомендуется). Перед вызовом chroot() выполняется chdir() в указанный каталог, поэтому если привилегии настроены нормально, покинуть chroot демон не сможет. Тем не менее, это накладывает свои ограничения:
- пути в виртуальных хостах должны быть относительны нового корня;
- в новом корне должен существовать как минимум
/dev/zero; - PID-файл создаётся относительно нового корня;
- что происходит с лог-файлами, пока сказать не могу, но есть подозрение что ротация логов без танцев с бубном работать не будет.
Сборка модуля:
./configure \ # Здесь идут обычные опции configure
--add-module=/path/to/ngx_drop_privs
make
Сен
2009
Комментарии к статье «ngx_drop_privs: принцип минимальных привилегий в nginx» (3) »
Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.
Оставить комментарий к записи «ngx_drop_privs: принцип минимальных привилегий в nginx»
गते गते पारगते पारसंगते बोधि स्वाहा
Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.


не проще ли сам nginx запустить в chroot?
Проще. Но права на
CAP_SYS_CHROOT,CAP_MKNOD,CAP_SYS_MODULEу мастер-процесса всё равно нужно отбирать, иначе он может выйти из chroot.Для тех, кто умеет пользоваться
bzr: самая последняя версия кода находится вbzr://bzr.sjinks.pro/ngx_drop_privs/trunk