Intereting Posts
Как предотвратить автоматический отключение внешнего внешнего жесткого диска Как изменить пользователя с аутентификацией внутри сценария оболочки Чтение с произвольного fd текущего процесса Включает ли установщик Linux Mint возможность заменить / обновить ТОЛЬКО Linux Mint на двойной системе загрузки? Как восстановить папки в исходное место назначения с использованием двуличия? Как подключить две виртуальные машины с разными диапазонами IP для доступа друг к другу? acpi_video0 яркость не влияет на экран Ошибка с командой make и sudo make install в терминале Как работает терминал Linux? Вот система V; как насчет систем I-IV? Попытка входа в систему Ubuntu tty Неинтерактивная настройка и установка портов FreeBSD Проблема декодирования вывода регулярного выражения {m, n} в sed Как сделать загрузочный pendrive для Kali Linux в системе UEFI? не запускать xorg при загрузке

Зачем мне использовать chroot для песочницы для безопасности, если мое приложение с самого начала может работать на более низком уровне?

Я пишу демон сервера HTTP на C (есть причины для этого), управляя им с помощью системного файла модуля.

Я переписываю приложение, разработанное 20 лет назад, примерно в 1995 году. И система, которую они используют, заключается в том, что они выполняют chroot, а затем setuid, и стандартную процедуру.

Теперь в моей предыдущей работе обычная политика заключалась в том, что вы никогда не запускаете какой-либо процесс от имени root. Вы создаете пользователя / группу для него и запускаете оттуда. Конечно, система запускала некоторые вещи от имени пользователя root, но мы могли бы выполнить всю обработку бизнес-логики, не будучи пользователем root

Теперь для HTTP-демона я могу запустить его без рута, если не выполняю chroot внутри приложения. Так разве не безопаснее, чтобы приложение никогда не запускалось от имени root?

Разве не безопаснее запускать его как пользователя mydaemon с самого начала? Вместо того, чтобы запускать его с правами root, chrooting, а затем setuid для mydaemon-user?

    Похоже, что другие не поняли вашу точку зрения, которая не была причиной использования измененных корней, о которых вы, конечно, уже хорошо знаете, и о том, что еще вы можете сделать, чтобы установить ограничения для деmonoв, когда вы также четко знаете о том, чтобы работать под эгидой непривилегированные учетные записи пользователей; но зачем делать это внутри приложения . На самом деле есть пример того, почему.

    Рассмотрим дизайн программы httpd dæmon в пакете publicfile Дэниела Дж. Бернштейна. Первое, что он делает, это меняет root на корневой каталог, который ему было сказано использовать с аргументом команды, затем отбрасывает привилегии для непривилегированного идентификатора пользователя и идентификатора группы, которые передаются в двух переменных среды.

    В наборах инструментов управления Dæmon есть специальные инструменты для таких вещей, как изменение корневого каталога и переход к непривилегированным идентификаторам пользователей и групп. У рун Геррита Папе есть chpst . У моего набора инструментов setuidgid-fromenv есть chroot и setuidgid-fromenv . У s6 Лорана Берко есть s6-chroot и s6-setuidgid . У runtool Уэйна Маршалла есть runtool и runuid . И так далее. Действительно, у всех них есть собственный набор инструментов setuidgid М. Бернштейна с setuidgid в качестве предшествующего setuidgid .

    Можно подумать, что можно извлечь функциональность из httpd и использовать такие специальные инструменты. Тогда, как вы предполагаете, ни одна часть серверной программы никогда не запускается с привилегиями суперпользователя.

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

    С httpd Бернштейна в его нынешнем виде единственными файлами и каталогами, которые находятся в дереве корневых каталогов, являются те, которые должны быть опубликованы в мире. На дереве больше ничего нет . Более того, нет никаких причин для того, чтобы файл образа исполняемой программы существовал в этом дереве.

    Но переместите замену корневого каталога в программу с загрузкой по цепочке (или systemd), и внезапно файл образа программы для httpd , любые совместно используемые библиотеки, которые он загружает, и любые специальные файлы в /etc , /run и /dev которые Доступ к загрузчику программы или библиотеке времени выполнения C во время инициализации программы (что может вас удивить, если вы используете программу C или 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 и т. д.)

    дальнейшее чтение

    • Даниэль Дж. Бернштейн (1996). httpd . публичный файл . cr.yp.to.
    • httpd . Программное обеспечение Даниэля Бернштейна все в одном . Softwares. Джонатан де Бойн Поллард. 2016.
    • gopherd Программное обеспечение Даниэля Бернштейна все в одном . Softwares. Джонатан де Бойн Поллард. 2017.
    • https://unix.stackexchange.com/a/353698/5132
    • https://github.com/janmojzis/httpfile/blob/master/droproot.c

    Я думаю, что многие детали вашего вопроса могут в равной степени относиться к avahi-daemon , который я недавно рассмотрел. (Возможно, я пропустил еще одну деталь, которая отличается). Запуск avahi-daemon в chroot имеет много преимуществ, если avahi-daemon скомпрометирован. Они include:

    1. он не может прочитать домашний каталог любого пользователя и удалить личную информацию.
    2. он не может использовать ошибки в других программах, записывая в / tmp. Существует как минимум одна целая категория таких ошибок. Например, https://www.google.co.uk/search?q=tmp+race+security+bug.
    3. он не может открыть любой файл сокета Unix, находящийся за пределами chroot, который другие демоны могут прослушивать и читать сообщения.

    Точка 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 или нет, и в самой изолированной программной среде, если оно все еще является корневым.) Эквивалентом описанной вами службы будет:

     [Service] ExecStart=/usr/local/bin/mydaemon User=mydaemon-user RootDirectory=... 

    Но мы не должны останавливаться на достигнутом. systemd также может сделать много других песочниц для вас – вот несколько примеров:

     [Service] # allocate separate /tmp and /var/tmp for the service PrivateTmp=yes # mount / (except for some subdirectories) read-only ProtectSystem=strict # empty /home, /root ProtectHome=yes # disable setuid and other privilege escalation mechanisms NoNewPrivileges=yes # separate network namespace with only loopback device PrivateNetwork=yes # only unix domain sockets (no inet, inet6, netlink, …) RestrictAddressFamilies=AF_UNIX 

    Смотрите man 5 systemd.exec чтобы man 5 systemd.exec больше директив и более подробных описаний. Если вы сделаете свой демон-активируемым сокет ( man 5 systemd.socket ), вы даже сможете использовать параметры, связанные с сетью: единственной ссылкой сервиса на внешний мир будет сетевой сокет, полученный от systemd, он не сможет подключиться к чему-либо еще. Если это простой сервер, который прослушивает только некоторые порты и не требует подключения к другим серверам, это может быть полезно. (Опции, относящиеся к файловой системе, также могут сделать RootDirectory устаревшим, на мой взгляд, поэтому, возможно, вам больше не придется настраивать новый корневой каталог со всеми необходимыми двоичными файлами и библиотеками.)

    Более новые версии systemd (начиная с v232) также поддерживают DynamicUser=yes , где systemd автоматически выделяет пользователя службы только для времени выполнения службы. Это означает, что вам не нужно регистрировать постоянного пользователя для службы, и он работает нормально, если служба не выполняет запись ни в какие местоположения файловой системы, кроме ее StateDirectory , LogsDirectory и CacheDirectory (которую вы также можете объявить в файл модуля – см. man 5 systemd.exec , снова – и каким systemd будет управлять, стараясь правильно назначить их динамическому пользователю).