
Низкоуровневый непривилегированный инструмент для песочницы, используемый Flatpak и аналогичными проектами.
Многие инструменты для работы с контейнерами, такие как systemd-nspawn, docker и т. д., ориентированы на предоставление инфраструктуры для системных администраторов и инструментов оркестрации (например, Kubernetes) для запуска контейнеров.
Эти инструменты не подходят для предоставления непривилегированным пользователям, поскольку превратить такой доступ в полностью привилегированную root-оболочку на хосте тривиально.
В ядре Linux есть функция под названием пользовательские пространства имён, которая позволяет непривилегированным пользователям использовать возможности контейнеров. Bubblewrap использует их для построения песочницы, позволяя любому пользователю использовать этот инструмент.
Исторически bubblewrap также поддерживал setuid-режим для систем, в которых не поддерживались непривилегированные пользовательские пространства имён. Однако эта возможность была удалена.
Изначальный код bubblewrap появился ещё до пользовательских пространств имён — он наследует код от xdg-app helper, который, в свою очередь, отдалённо происходит от linux-user-chroot.
Сопровождающие этого инструмента считают, что он, даже при использовании в сочетании с типовым программным обеспечением, установленным в этом дистрибутиве, не позволяет повышать привилегии. Однако он может повысить способность вошедшего в систему пользователя совершать атаки типа «отказ в обслуживании».
В частности, bubblewrap использует PR_SET_NO_NEW_PRIVS для отключения setuid-бинарных файлов, что является традиционным способом выбраться из таких ограничений, как chroot.
bubblewrap — это инструмент для создания сред песочницы. bubblewrap не является полной, готовой песочницей с определённой политикой безопасности.
Некоторые сценарии использования bubblewrap требуют наличия границы безопасности между песочницей и реальной системой; другие сценарии использования хотят иметь возможность изменять структуру файловой системы для процессов внутри песочницы, но не претендуют на роль границы безопасности. В результате уровень защиты между процессами в песочнице и хост-системой полностью определяется аргументами, переданными bubblewrap.
Какая бы программа ни формировала аргументы командной строки для bubblewrap (часто это более крупный фреймворк, такой как Flatpak, libgnome-desktop, sandwine или специальный скрипт), именно она отвечает за определение собственной модели безопасности и выбор подходящих аргументов командной строки bubblewrap для реализации этой модели безопасности.
Некоторые аспекты безопасности песочницы, требующие особого внимания, описаны в разделе Ограничения ниже.
Эта программа может использоваться совместно всеми инструментами для контейнеров, которые работают без прав root, например:
Мы также хотели бы, чтобы эта возможность была доступна в кластерах Kubernetes/OpenShift. Наличие возможности использовать функции контейнеров непривилегированным пользователям значительно упростило бы интерактивную отладку и подобные сценарии.
bubblewrap доступен в репозиториях пакетов большинства дистрибутивов Linux и может быть установлен оттуда.
Если вам нужно собрать bubblewrap из исходного кода, вы можете сделать это с помощью meson:
meson _builddir
meson compile -C _builddir
meson test -C _builddir
meson install -C _builddir
bubblewrap работает следующим образом: он создаёт новое, полностью пустое пространство имён монтирования, в котором корень находится на tmpfs, невидимой для хоста и автоматически очищаемой после завершения последнего процесса. Затем вы можете использовать параметры командной строки, чтобы сконструировать корневую файловую систему, окружение процесса и команду для запуска в этом пространстве имён.
В исходном коде есть более крупный демонстрационный скрипт, но здесь приведена урезанная версия, которая запускает новую оболочку, используя /usr хоста.
bwrap \
--ro-bind /usr /usr \
--symlink usr/lib64 /lib64 \
--proc /proc \
--dev /dev \
--unshare-pid \
--new-session \
bash
Это неполный пример, но он полезен для иллюстрации. Чаще, чем создавать контейнер с использованием дерева файловой системы хоста, вы хотите использовать chroot. В этом случае, вместо создания символической ссылки lib64 -> usr/lib64 в tmpfs, вы, возможно, уже создали её в целевой корневой файловой системе.
Цель bubblewrap — запускать приложение в песочнице, где оно имеет ограниченный доступ к частям операционной системы или пользовательским данным, таким как домашний каталог.
bubblewrap всегда создаёт новое пространство имён монтирования, и пользователь может точно указать, какие части файловой системы должны быть видны в песочнице. Любые такие каталоги, которые вы указываете, по умолчанию монтируются с опцией nodev и могут быть сделаны доступными только для чтения.
Кроме того, вы можете использовать следующие возможности ядра:
Пользовательские пространства имён (CLONE_NEWUSER): Это скрывает от песочницы всё, кроме текущих uid и gid. Вы также можете изменить значение uid/gid в песочнице.
Пространства имён IPC (CLONE_NEWIPC): Песочница получит собственную копию всех различных форм IPC, таких как разделяемая память SysV и семафоры.
Пространства имён PID (CLONE_NEWPID): Песочница не увидит никаких процессов вне песочницы. Кроме того, bubblewrap запустит тривиальный pid1 внутри вашего контейнера для обработки требований по сбору зомби-процессов в песочнице. Это позволяет избежать того, что сейчас известно как проблема Docker pid 1.
Сетевые пространства имён (CLONE_NEWNET): Песочница не увидит сеть. Вместо этого у неё будет собственное сетевое пространство имён только с loopback-устройством.
Пространство имён UTS (CLONE_NEWUTS): Песочница будет иметь собственное имя хоста.
Фильтры seccomp: Вы можете передавать фильтры seccomp, которые ограничивают, какие системные вызовы можно выполнять в песочнице. Для получения дополнительной информации см. Seccomp.
Как отмечалось в разделе Безопасность песочницы выше, уровень защиты между процессами в песочнице и хост-системой полностью определяется аргументами, переданными bubblewrap. Некоторые аспекты, требующие особого внимания, отмечены здесь.
Если вы не отфильтровываете команды TIOCSTI с помощью фильтров seccomp, аргумент --new-session необходим для защиты от выполнения команд за пределами песочницы (см. CVE-2017-5226).
Всё, что смонтировано в песочницу, потенциально может быть использовано для повышения привилегий. Например, если вы привяжете сокет D-Bus в песочницу, его можно будет использовать для выполнения команд через systemd. Вы можете использовать xdg-dbus-proxy для фильтрации обмена данными D-Bus.
Некоторые приложения разворачивают собственные механизмы песочницы, и они могут быть ограничены ограничениями, налагаемыми песочницей bubblewrap. Например, некоторые веб-браузеры, которые настраивают свои дочерние процессы через seccomp так, чтобы они не имели доступа к файловой системе. Если вы ограничите системные вызовы и не разрешите системный вызов seccomp, браузер не сможет применить эти ограничения. Аналогично, если эти правила скомпилированы в файл, недоступный в песочнице, браузер не сможет загрузить эти правила из этого файла и не сможет применить эти ограничения.
Firejail похож на Flatpak до выделения bubblewrap тем, что он сочетает setuid-инструмент с множеством специфичных для рабочего стола функций песочницы. Например, Firejail знает о Pulseaudio, тогда как bubblewrap — нет.
Авторы bubblewrap считают, что аудировать небольшую setuid-программу гораздо проще, а такие функции, как фильтрация Pulseaudio, лучше оставить непривилегированному процессу, как это сейчас происходит во Flatpak.
Кроме того, @cgwalters считает, что попытка вносить пути файлов в белый список — плохая идея, учитывая бесчисленные способы, которыми пользователи могут манипулировать путями, и бесчисленные способы, которыми системные администраторы могут настраивать систему. Подход bubblewrap заключается в том, чтобы сохранить лишь несколько конкретных capabilities Linux, таких как CAP_SYS_ADMIN, но всегда обращаться к файловой системе от имени вызывающего uid. Это полностью закрывает TOCTTOU-атаки и тому подобное.
Sandstorm.io требует непривилегированных пользовательских пространств имён для настройки своей песочницы, хотя его можно легко адаптировать для работы и в setuid-режиме. @cgwalters считает, что их код довольно хорош, но всё равно может иметь смысл объединиться вокруг bubblewrap. Однако @kentonv (из Sandstorm) считает, что хотя в принципе это разумно, затраты на переход перевешивают практические выгоды на данный момент. Это решение может быть пересмотрено в будущем, но сегодня оно активно не прорабатывается.
runC в настоящее время работает над поддержкой rootless-контейнеров без необходимости setuid или каких-либо других привилегий при установке runC (используя непривилегированные пользовательские пространства имён, а не setuid), создании и управлении контейнерами. Однако стандартный режим использования runC похож на systemd nspawn тем, что это инструмент, предназначенный для запуска от имени root.
Авторы bubblewrap считают, что runc и systemd-nspawn не рассчитаны на то, чтобы быть setuid, и далеки от поддержки такого режима. Однако с rootless-контейнерами runC сможет выполнять определённые сценарии использования, которые поддерживает bubblewrap (с дополнительным преимуществом в виде стандартизированного и полного OCI-runtime).
binctr — это просто обёртка над runC, поэтому он наследует все его компромиссы в дизайне.
Название bubblewrap было выбрано, чтобы передать, что этот инструмент работает как родитель приложения (то есть в некотором смысле оборачивает его) и создаёт вокруг него защитный слой (песочницу).

(Кот Bubblewrap от dancing_stupidity)