Я пишу демон HTTP-сервера на C (есть причины, почему), управляя им с помощью системного файла модуля.
Я переписываю приложение, разработанное 20 лет назад, примерно в 1995 году. И система, которую они используют, заключается в том, что они выполняют chroot, а затем setuid, и стандартную процедуру.
Теперь, в моей предыдущей работе, обычной политикой было то, что вы никогда не запускаете какой-либо процесс от имени пользователя root. Вы создаете пользователя / группу для него и запускаете оттуда. Конечно, система выполняла некоторые функции от имени пользователя root, но мы могли выполнить всю обработку бизнес-логики, не будучи пользователем root.
Теперь для HTTP-демона я могу запустить его без рута, если не выполняю chroot внутри приложения. Так не безопаснее ли, чтобы приложение никогда не запускалось от имени root?
Разве не безопаснее запускать его как mydaemon-user с самого начала? Вместо того, чтобы запускать его с правами root, chrooting, а затем setuid для mydaemon-user?
capabilities(7)
.Ответы:
Похоже, что другие не поняли вашу точку зрения, которая не была причиной, по которой нужно использовать измененные корни, что, конечно же, вы уже ясно знаете, и что еще вы можете сделать, чтобы установить ограничения на демонов, когда вы также четко знаете о работе под эгидой непривилегированные учетные записи пользователей; но зачем делать это внутри приложения . На самом деле есть пример того, почему.
Рассмотрим дизайн
httpd
программы демона в пакете публичных файлов Дэниела Дж. Бернштейна. Первое, что он делает, это меняет root на корневой каталог, который ему было сказано использовать с аргументом команды, затем отбрасывает привилегии для непривилегированного идентификатора пользователя и идентификатора группы, которые передаются в двух переменных среды.Наборы инструментов управления Dæmon имеют специальные инструменты для таких вещей, как изменение корневого каталога и переход к непривилегированным идентификаторам пользователей и групп. Рунит Геррита Папе имеет
chpst
. Мой набор инструментов Nosh имеетchroot
иsetuidgid-fromenv
. S6 Лорана Беркота имеетs6-chroot
иs6-setuidgid
. У Уэйна Маршалла естьruntool
и Перпrunuid
. И так далее. Действительно, у них всех есть собственный набор инструментов daemontools М. Бернштейнаsetuidgid
в качестве антецедента.Можно подумать, что можно извлечь функциональность
httpd
и использовать такие специальные инструменты. Тогда, как вы предполагаете, ни одна часть серверной программы никогда не запускается с привилегиями суперпользователя.Проблема в том, что в качестве прямого следствия нужно выполнить значительно больше работы для настройки измененного корня, и это открывает новые проблемы.
С Бернштейном
httpd
в его нынешнем виде единственными файлами и каталогами в дереве корневых каталогов являются те, которые должны быть опубликованы в мире. На дереве больше ничего нет . Кроме того, нет никаких оснований для любого исполняемого файла программы изображения существуют в этом дереве.Но переместить изменение корневого каталога из в программу цепи нагрузки (или Systemd), и вдруг программный файл изображения для
httpd
, любых общих библиотек , которые он загружает, а также любые специальные файлы/etc
,/run
и/dev
что загрузчик программы или C Runtime библиотеки доступа во время инициализации программы (которые вы можете найти весьма удивительно , еслиtruss
/strace
с или C ++ программа), также должны присутствовать в измененном корне. Иначеhttpd
не может быть прикован к цепи и не будет загружаться / работать.Помните, что это сервер содержимого HTTP (S). Он может потенциально обслуживать любой (читаемый миром) файл в измененном корне. Теперь это включает в себя такие вещи, как ваши общие библиотеки, ваш загрузчик программ и копии различных файлов конфигурации загрузчика / CRTL для вашей операционной системы. И если каким-либо (случайным) образом сервер содержимого имеет доступ для записи , скомпрометированный сервер может получить доступ на запись к образу программы для
httpd
себя или даже для загрузчика программ вашей системы. (Помните , что у вас есть два параллельных набора/usr
,/lib
,/etc
,/run
, и/dev
каталоги , чтобы сохранить в безопасности.)Ничего из этого не имеет место, когда
httpd
меняет root и сам отбрасывает привилегии.Итак, вы торгуете с небольшим количеством привилегированного кода, который довольно легко проверять и который запускается в самом начале
httpd
программы, с привилегиями суперпользователя; за значительно расширенную поверхность атаки файлов и каталогов внутри измененного корня.Вот почему это не так просто, как делать все внешне для сервисной программы.
Обратите внимание, что это, тем не менее, минимальный уровень функциональности внутри
httpd
себя. Весь код, который выполняет такие вещи, как поиск в базе данных учетных записей операционной системы идентификатора пользователя и группы для помещения в эти переменные среды, в первую очередь, является внешним по отношению кhttpd
программе в простых автономных проверяемых командах, таких какenvuidgid
. (И, конечно , это инструмент UCSPI, поэтому она содержит ни один из кодов не прослушивать соответствующий TCP порт (ы) или принимать соединения, те , будучи областью команд , таких какtcpserver
,tcp-socket-listen
,tcp-socket-accept
,s6-tcpserver4-socketbinder
,s6-tcpserver4d
, и так далее.)дальнейшее чтение
httpd
, публичный файл . cr.yp.to.httpd
, Программное обеспечение Даниэля Бернштейна все в одном . Softwares. Джонатан де Бойн Поллард. 2016.gopherd
, Программное обеспечение Даниэля Бернштейна все в одном . Softwares. Джонатан де Бойн Поллард. 2017.источник
Я думаю, что многие детали вашего вопроса могут в равной степени относиться к тому
avahi-daemon
, на что я смотрел недавно. (Возможно, я пропустил еще одну деталь, которая отличается). Запуск avahi-daemon в chroot имеет много преимуществ, если avahi-daemon скомпрометирован. Это включает:Пункт 3 может быть особенно приятным, когда вы не используете dbus или аналогичный ... Я думаю, что avahi-daemon использует dbus, поэтому он обеспечивает постоянный доступ к системному dbus даже изнутри chroot. Если вам не нужна возможность отправлять сообщения в системный dbus, отрицание этой возможности может быть довольно хорошей функцией безопасности.
Обратите внимание, что если avahi-daemon был переписан, он может предпочесть полагаться на systemd для обеспечения безопасности и использовать, например,
ProtectHome
. Я предложил изменить avahi-daemon, чтобы добавить эти защиты в качестве дополнительного слоя, а также некоторые дополнительные защиты, которые не гарантируются chroot. Вы можете увидеть полный список вариантов, которые я предложил здесь:https://github.com/lathiat/avahi/pull/181/commits/67a7b10049c58d6afeebdc64ffd2023c5a93d49a
Похоже, есть и другие ограничения, которые я мог бы использовать, если бы avahi-daemon не использовал сам chroot, некоторые из которых упоминаются в сообщении коммита. Я не уверен, насколько это относится, хотя.
Обратите внимание, что защита, которую я использовал, не ограничивала бы демона открытием файлов сокетов Unix (пункт 3 выше).
Другой подход заключается в использовании SELinux. Однако вы бы как бы привязывали свое приложение к этому подмножеству дистрибутивов Linux. Причина, по которой я положительно отнесся к SELinux, заключается в том, что SELinux детально ограничивает доступ, который имеют процессы к dbus. Например, я думаю, что вы часто можете ожидать, что
systemd
этого не будет в списке названий шин, на которые вам нужно было отправлять сообщения :-).«Мне было интересно, если использование системной песочницы безопаснее, чем chroot / setuid / umask / ...»
Резюме: почему не оба? Давайте немного расшифруем вышесказанное :-).
Если вы думаете о пункте 3, использование chroot обеспечивает больше ограничений. ProtectHome = и его друзья даже не пытаются быть такими же строгими, как chroot. (Например, ни один из именованных опций systemd не
/run
помещается в черный список , куда мы склонны помещать файлы сокетов Unix).chroot показывает, что ограничение доступа к файловой системе может быть очень мощным, но не все в Linux является файлом :-). Есть системные опции, которые могут ограничивать другие вещи, которые не являются файлами. Это полезно, если программа скомпрометирована, вы можете уменьшить возможности ядра, доступные для нее, в которых она может попытаться использовать уязвимость. Например, avahi-daemon не требует Bluetooth-сокетов, и я полагаю, что ваш веб-сервер тоже не нуждается :-). Так что не предоставляйте ему доступ к семейству адресов AF_BLUETOOTH. Просто белый список AF_INET, AF_INET6 и, возможно, AF_UNIX, используя
RestrictAddressFamilies=
опцию.Пожалуйста, прочитайте документы для каждого варианта, который вы используете. Некоторые параметры более эффективны в сочетании с другими, а некоторые доступны не на всех архитектурах ЦП. (Не потому, что процессор плохой, а потому, что порт Linux для этого процессора не был так хорошо спроектирован. Я думаю).
(Здесь есть общий принцип. Это более безопасно, если вы можете писать списки того, что вы хотите разрешить, а не того, что вы хотите запретить. Например, определение chroot дает вам список файлов, к которым у вас есть доступ, и это более надежно чем сказать, что вы хотите заблокировать
/home
).В принципе, вы можете применить все те же ограничения самостоятельно перед setuid (). Это всего лишь код, который вы можете скопировать из systemd. Тем не менее, параметры системного блока должны быть значительно проще для написания, и, поскольку они представлены в стандартном формате, их будет легче читать и просматривать.
Поэтому я настоятельно рекомендую просто прочитать раздел «песочница»
man systemd.exec
на вашей целевой платформе. Но если вы хотите наиболее безопасный дизайн можно, я не боялся бы попробоватьchroot
(а затем удалитьroot
привилегии) в вашей программе , а также . Здесь есть компромисс. Использованиеchroot
накладывает некоторые ограничения на ваш общий дизайн. Если у вас уже есть дизайн, использующий chroot, и, кажется, он делает то, что вам нужно, это звучит довольно здорово.источник
Если вы можете положиться на systemd, то безопаснее (и проще!) Оставить песочницу для systemd. (Конечно, приложение может также определить, была ли оно запущено в изолированной программной среде с помощью systemd или нет, и в самой изолированной программной среде, если оно все еще является корневым.) Эквивалентом описанной вами службы будет:
Но мы не должны останавливаться на достигнутом. systemd также может сделать много других песочниц для вас - вот несколько примеров:
Смотрите
man 5 systemd.exec
больше директив и более подробных описаний. Если вы сделаете свой демон-активируемый сокет (man 5 systemd.socket
), вы даже сможете использовать параметры, связанные с сетью: единственной ссылкой службы на внешний мир будет сетевой сокет, полученный от systemd, и он не сможет подключиться ни к чему другому. Если это простой сервер, который прослушивает только некоторые порты и не требует подключения к другим серверам, это может быть полезно. (НаRootDirectory
мой взгляд, параметры, связанные с файловой системой, также могут устареть, так что, возможно, вам больше не придется настраивать новый корневой каталог со всеми необходимыми двоичными файлами и библиотеками.)Также поддерживаются более новые версии systemd (начиная с версии v232)
DynamicUser=yes
, где systemd автоматически назначает пользователя службы только для времени выполнения службы. Это означает , что вы не должны зарегистрировать постоянный пользователь для службы, и работаете отлично до тех пор , как служба не пишете ни файловая систему мест , отличных от егоStateDirectory
,LogsDirectory
иCacheDirectory
(вы можете также объявить в единичном файле - смотритеman 5 systemd.exec
, опять же - и какой systemd будет управлять, заботясь о том, чтобы правильно назначить их динамическому пользователю).источник