Bubblewrap
Bubblewrap 是一个轻量级的沙盒应用,被 Flatpak 和其他容器工具使用。它安装体积小,资源需求极低。虽然软件包名为 bubblewrap,但实际的命令行界面是 bwrap(1)。值得注意的功能包括支持 cgroup/IPC/mount/network/PID/user/UTS 命名空间 和 seccomp 过滤。请注意,bubblewrap 会丢弃沙盒内的所有 capabilities,并且子任务无法获得比其父任务更高的权限。值得注意的功能排除包括缺乏对黑名单/白名单文件路径的显式支持。
安装
安装 bubblewrap 或 bubblewrap-gitAUR。
- 有关 Arch Linux 内核中 user_namespaces(7) 支持的信息,请参阅 安全性#沙盒化应用程序。
- linux-hardened 用户可能需要安装 bubblewrap-suid 而不是上面提到的软件包。有关更多信息,请参阅 FS#63316。
配置
Bubblewrap 可以直接从命令行调用,也可以在 shell 脚本 中作为 复杂包装器 的一部分调用。与 Firejail 等应用程序不同,后者会自动将沙盒内的 /var
和 /etc
设置为只读,Bubblewrap 没有做这样的操作假设。用户需要根据要沙盒化的应用程序确定要传递哪些配置选项。当使用 setuid 权限运行时,Bubblewrap 不会自动创建用户命名空间,并且可以适应典型的环境变量,包括 $HOME
和 $USER
。
强烈建议您下载 strace,以查看您尝试沙盒化的程序需要访问哪些文件。
bubblewrap 的配置管理器
可以使用配置管理器而不是手动设置参数,配置管理器可以从更简单的配置中自动配置 bubblewrap。
- Bubblejail — 基于 Bubblewrap 的沙盒,具有基于资源的权限模型(提供 GUI 来调整权限)。
- portableAUR:易于使用的沙盒框架,包括 D-Bus 代理过滤、数据隔离、访问控制等。
使用示例
请参阅 /Examples 以获取有关如何使用 bubblewrap 的示例。或者,有许多项目演示了如何将 bubblewrap 用于常见应用程序
无操作
无操作的 bubblewrap 调用如下所示
$ bwrap --dev-bind / / bash
这将产生一个 Bash 进程,在大多数情况下,它的行为应该与在沙盒外完全相同。如果沙盒程序行为异常,您可能需要从上面的无操作调用开始,并逐步改进到更安全的配置。
nobody
,这意味着运行 sudo
之类的程序将无法正常工作。Bash
创建一个简单的 Bash 沙盒
- 确定可用的内核命名空间
$ ls /proc/self/ns
cgroup ipc mnt net pid user uts
user
的存在表明内核已通过 CONFIG_USER_NS=y
公开了对用户命名空间的支持$ bwrap --ro-bind / / --unshare-user --uid 256 --gid 512 bash
bash-4.4$ id uid=256 gid=512 groups=512,65534(nobody) bash-4.4$ ls -l /usr/bin/bash -rwxr-xr-x 1 nobody nobody 811752 2017-01-01 04:20 /usr/bin/bash
桌面条目
在 桌面条目 中利用 Bubblewrap
- 将整个主机
/
目录作为读写绑定到沙盒中的/
- 将
/var
和/etc
目录在沙盒中重新绑定为只读 - 在沙盒中的
/dev
上挂载一个新的 devtmpfs 文件系统 - 在沙盒化的
/run
目录上创建一个 tmpfs 文件系统 - 通过创建新的网络命名空间来禁用网络访问
[Desktop Entry] Name=nano Editor Exec=bwrap --bind / / --dev /dev --tmpfs /run --unshare-net st -e nano -o . %f Type=Application MimeType=text/plain;
--dev /dev
才能写入 /dev/pty
- 包含
mupdf.sh
shell 包装器的 MuPDF 桌面条目示例
[Desktop Entry] Name=MuPDF Exec=mupdf.sh %f Icon=application-pdf.svg Type=Application MimeType=application/pdf;application/x-pdf;
mupdf.sh
位于您的可执行 PATH 中,例如 PATH=$PATH:$HOME/bwrap
文件系统隔离
为了进一步隐藏文件系统的内容(例如 /var
、/usr/bin
和 /usr/lib
中的内容)并沙盒化软件安装,可以使 pacman 将 Arch 软件包安装到隔离的文件系统树中。
为了使用 pacman 将软件安装到文件系统树中,您需要安装 fakeroot 和 fakechroot。
假设您想使用 pacman 将 xterm
软件包安装到隔离的文件系统树中。您应该像这样准备您的树
$ MYPACKAGE=xterm $ mkdir -p ~/sandboxes/${MYPACKAGE}/files/var/lib/pacman $ mkdir -p ~/sandboxes/${MYPACKAGE}/files/etc $ cp /etc/pacman.conf ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf
您可能想要编辑 ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf
并调整使用的 pacman 配置
- 删除任何不需要的自定义存储库以及仅主机系统需要的
IgnorePkg
、IgnoreGroup
、NoUpgrade
和NoExtract
设置。 - 您可能需要删除
CheckSpace
选项,这样 pacman 就不会抱怨找不到根文件系统来检查磁盘空间而报错。
然后将 base
组以及所需的 fakeroot 安装到隔离的文件系统树中
$ fakechroot fakeroot pacman -Syu \ --root ~/sandboxes/${MYPACKAGE}/files \ --dbpath ~/sandboxes/${MYPACKAGE}/files/var/lib/pacman \ --config ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf \ base fakeroot
由于您将重复使用相同的选项调用 bubblewrap,因此创建一个别名
$ alias bw-install='bwrap \ --bind ~/sandboxes/${MYPACKAGE}/files/ / \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --tmpfs /tmp \ --proc /proc \ --dev /dev \ --chdir / '
您将需要通过 编辑 ~/sandboxes/${MYPACKAGE}/files/etc/locale.gen
并运行以下命令来设置 locale
$ bw-install locale-gen
然后设置 pacman 的密钥环
$ bw-install fakeroot pacman-key --init $ bw-install fakeroot pacman-key --populate
现在您可以安装所需的 xterm
软件包。
$ bw-install fakeroot pacman -S ${MYPACKAGE}
如果 pacman 命令在此处失败,请尝试再次运行用于填充密钥环的命令。
恭喜。您现在有了一个包含 xterm
的隔离文件系统树。您可以再次使用 bw-install
来升级您的文件系统树。
您现在可以使用 bubblewrap 运行您的软件。在这种情况下,command
应该是 xterm
。
$ bwrap \ --ro-bind ~/sandboxes/${MYPACKAGE}/files/ / \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --tmpfs /tmp \ --proc /proc \ --dev /dev \ --chdir / \ command
请注意,某些文件可以在软件包之间共享。您可以硬链接到现有父文件系统树的所有文件,以便在新树中重用它们
$ cp -al ~/sandboxes/${MYPARENTPACKAGE} ~/sandboxes/${MYPACKAGE}
然后像往常一样继续安装,从 bw-install fakechroot fakeroot pacman ...
调用 pacman。
故障排除
使用 X11
将主机 X11 套接字绑定挂载到备用 X11 套接字可能不起作用
--bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X8 --setenv DISPLAY :8
一种解决方法是将主机 X11 套接字绑定挂载到沙盒内的同一套接字
--bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 --setenv DISPLAY :0
沙盒化 X11
虽然 bwrap 为沙盒应用程序提供了一些非常好的隔离,但只要可以访问 X11 套接字,就很容易逃脱。X11 不包含应用程序之间的隔离,并且完全不安全。唯一的解决方案是切换到 Wayland 合成器,并且从沙盒中无法访问 Xserver。
但是,有一些使用 xpra 或 xephyr 在新的 X11 环境中运行的解决方法。这也可以与 bwrap 一起使用。
要测试 X11 隔离,请运行 xinput test id
(键盘 id 可以使用 xinput list
找到)。在没有额外的 X11 隔离的情况下运行时,这将表明任何具有 X11 访问权限的应用程序都可以捕获任何其他应用程序的键盘输入,这基本上是键盘记录器会做的事情。
消除 X11 弱点的最佳解决方案是切换到 Wayland 合成器。
使用 portal
xdg-desktop-poral
认为沙盒程序是 Flatpak。提醒一下,运行不受信任的代码永远是不安全的,即使在沙盒中,即使使用 Portal 也是如此通过一些解决方法,可以使用 XDG Desktop Portal 对程序进行沙盒化。主要优点是文件系统 portal,因为它使得可以在不给程序访问主目录的情况下仍然能够访问文件。出于安全原因,但是,使用 portal 需要欺骗 xdg-desktop-portal
认为沙盒程序是 Flatpak 的一部分。这可以通过向沙盒的根文件系统添加 .flatpak-info
文件来完成。
此外,还需要运行 xdg-dbus-proxy
以更精细地控制可以访问哪些 portal。这应该在沙盒环境中运行,因此也需要 .flatpak-info
文件。至少,代理需要具有与 org.freedesktop.portal.Flatpak
通信的访问权限。可以在 Flatpak 文档 中找到其他 portal。
一个常见的用例是允许限制程序对主目录的 100% 访问权限,而是仅授予对用户在文件选择器中选择的文件和文件夹的访问权限。为了实现这一点,可以使用以下参数启动 xdg-dbus-proxy
--talk=org.freedesktop.portal.Documents --talk=org.freedesktop.portal.Flatpak --talk=org.freedesktop.portal.Desktop --talk=org.freedesktop.portal.FileChooser
完整示例
APP_NAME=app.application.Name APP_FOLDER="$XDG_RUNTIME_DIR/app/$APP_NAME" mkdir -p "$APP_FOLDER" set_up_dbus_proxy() { bwrap \ --new-session \ --symlink /usr/lib64 /lib64 \ --ro-bind /usr/lib /usr/lib \ --ro-bind /usr/lib64 /usr/lib64 \ --ro-bind /usr/bin /usr/bin \ --bind "$XDG_RUNTIME_DIR" "$XDG_RUNTIME_DIR" \ --ro-bind-data 3 "/.flatpak-info" \ --die-with-parent \ -- \ env -i xdg-dbus-proxy \ "$DBUS_SESSION_BUS_ADDRESS" \ "$APP_FOLDER/bus" \ --filter \ --log \ --talk=org.freedesktop.portal.Flatpak \ --call="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.Read@/org/freedesktop/portal/desktop" \ --broadcast="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.SettingChanged@/org/freedesktop/portal/desktop" 3<<EOF [Application] name=$APP_NAME EOF } set_up_dbus_proxy & sleep 0.1 bwrap \ ... --ro-bind-data 3 /.flatpak-info \ ... 3<<EOF [Application] name=$APP_NAME EOF
从包装的应用打开 URL
当包装的 IRC 或电子邮件客户端尝试打开 URL 时,它通常会尝试启动浏览器进程,该进程将在与包装的应用程序相同的沙盒中运行。对于包装良好的应用程序,这可能无法正常工作。Firejail 使用的方法是 也授予包装的应用程序浏览器的所有权限,但这暗示了大量的权限蔓延。
解决此问题的更好方法是将打开的 URL 传递到沙盒外部。这可以使用 snapd-xdg-open
完成,如下所示
- 安装 snapd-xdg-open-gitAUR
- 在您的
bwrap
命令行中,添加
$ bwrap ... \ --ro-bind /run/user/$UID/bus /run/user/$UID/bus \ --ro-bind /usr/lib/snapd-xdg-open/xdg-open /usr/bin/xdg-open \ --ro-bind /usr/lib/snapd-xdg-open/xdg-open /usr/bin/chromium \ ...
/usr/bin/chromium
绑定仅对于不使用 XDG 约定的程序是必需的,例如 Mozilla Thunderbird。
新会话
TIOCSTI 存在安全问题 (CVE-2017-5226),这允许沙盒逃逸。为了防止这种情况,bubblewrap 引入了新的选项“--new-session”,它调用 setsid()。但是,这会导致一些行为问题,在某些情况下很难处理。例如,它使 shell 作业控制对于 bwrap 命令不起作用。
如果可能,建议使用此选项,但如果不能,开发人员建议以其他方式消除此问题,例如使用 SECCOMP,这正是 flatpak 所做的:https://github.com/flatpak/flatpak/commit/902fb713990a8f968ea4350c7c2a27ff46f1a6c4
嵌套命名空间
某些应用程序(例如 Chromium)已经使用 suid 辅助文件实现了自己的沙盒环境。当它们在 bubblewrap 容器内执行时,此机制将被阻止。
一种解决方案是让应用程序使用由 bubblewrap 创建的命名空间。这可以通过 zypakAUR 实现,flatpak 也使用 zypak 在额外的命名空间内运行基于 electron 的应用程序。可以在 [1] 找到演示如何将 zypak 与 Chromium/Electron 一起使用的示例代码。
无声音输出
对于使用 ALSA 声音系统的某些程序,请添加
--dev-bind /dev/snd /dev/snd
以播放声音。