我/var/mychoot
在与 相同的文件系统上有一个目录/
,并且我已将程序启动/var/mychroot/prog
为sudo chroot /var/mychroot /prog
,因此程序以 EUID 0 运行。
如果程序执行chdir("..") 转义技术,则它能够转义 chroot 并查看/
. (我已经在 Linux 4.18 上验证了这一点。)
我想阻止这样的逃跑。事实上,我想防止各种 chroot 转义,但在这个问题中,我只对如何在现代 Linux 系统上防止chdir("..") 转义技术感兴趣。为此,我正在寻找chroot(2)系统调用的替代方案。
我找到了 2 个解决方案:pivot_root和MS_MOVE,但它们仅在/var/mychroot
是挂载点时才有效,因此如果/var/mychroot
只是/
文件系统中的子目录,它们就会失败。在这种情况下还有其他解决方案吗?
我想避免使用技术LD_PRELOAD
(因为LD_PRELOAD
不影响静态链接的可执行文件),使用ptrace(2)的技术(因为这样我就无法strace
在 chroot 中运行,而且ptrace(2)也很难正确处理:进程将崩溃或挂起)和真正的虚拟化(例如 Xen 或 KVM 或 QEMU;因为性能开销和不太灵活的内存配置)。
回顾一下,我需要:
- chroot(2)系统调用的替代方案,
- root 可以限制以 root 身份运行的进程(EUID 0),
- 到文件系统的子目录
/
, - 这可以防止chdir("..") 转义技术,
- 并且不使用
LD_PRELOAD
或 - ptrace(2)或
- 虚拟化(例如 Xen、KVM 或 QEMU),
- 它运行在现代 Linux 系统上,
- 带有未打补丁的内核。
它存在吗?
为了防止
chdir("..")
您提到的特定逃生技术,您可以简单地放弃在chroot(2)
您自己 chroot 后再次执行的能力/var/mychroot
。转义技术需要再次调用chroot()
,因此阻止它足以阻止它工作。您可以使用 Linux 功能来做到这一点,方法是删除
CAP_SYS_CHROOT
需要chroot(2)
可用的功能。例如:
(chroot 中的第二个提示符来自一个由 . 生成的 shell
capsh
。你可以让它运行另一个命令,例如capsh --drop=cap_sys_chroot -- -c 'exec ./escape_chroot'
,但是更好的技术是只使用
pivot_root
,因为它可以防止许多其他可能chroot(2)
无法防止的漏洞。您提到它仅在
/var/mychroot
是挂载点时才有效,但是您可以通过简单地将挂载绑定到自身来使其成为挂载点。请注意,您需要创建一个挂载命名空间以用于
pivot_root
创建监狱,否则它将尝试更改文件系统中所有进程的根目录,这很可能不是您想要的...所以整个序列是:
(同样,这些命令中的许多都在生成新的 shell。
unshare
这样做,chroot
本身也是如此。您可以通过将命令作为额外参数传递来解决这些问题。在某些情况下,您可能希望传递sh -c '...'
完整的脚本。)在这一点上,你
pivot_root
在一个单独的挂载命名空间的监狱里,事实上它/var/mychroot
只是原始根目录的一个目录(而不是一个单独的设备或循环设备的挂载)并没有真正阻止它工作,由于绑定安装到自身。运行转义码,你会看到监狱按预期工作(即使转义码声称不是这样):
如您所见,仍然在监狱中......漏洞利用代码有点天真,并假设只要操作(
chroot
,chdir
)成功,就足以逃离监狱,事实并非如此...... .所以考虑使用这种技术来创建一个优于
chroot
并且不需要使用 Linux 功能来阻止其中的操作的监狱(例如创建额外chroot
的 s,这实际上可能对您实际尝试运行的内容有用或需要)监狱。)您可以将任何目录设置为挂载点:
mount --rbind /var/mychoot /var/mychoot
.这一步 - 以及您需要的其他步骤 - 在这里介绍:
如何使用 Linux 命名空间执行 chroot?
将上述内容与用户命名空间结合起来。
或者,
seccomp
。例如,这就是 Docker 阻止包含进程调用mount()
的方式。(当您第二次挂载块设备时,您将获得该文件系统的第二个视图,这或多或少算作逃逸)。复制 Docker 允许的系统调用列表 - root 有很多不同的转义方式。https://docs.docker.com/engine/security/seccomp/
https://github.com/moby/moby/blob/master/profiles/seccomp/default.json