如何在 Linux 上的文件系统内使用 chdir("..") 创建一个 root 无法逃脱的 chroot?

如何在 Linux 上的文件系统内使用 chdir("..") 创建一个 root 无法逃脱的 chroot?

/var/mychoot我在与 相​​同的文件系统上有一个目录/,并且我已将程序启动/var/mychroot/progsudo chroot /var/mychroot /prog,因此该程序以 EUID 0 运行。

如果程序执行chdir("..") 转义技术,然后它就能够逃脱 chroot 并看到里面的一切/。 (我已经在 Linux 4.18 上验证了这一点。)

我想阻止这样的逃跑。事实上我想防止各种 chroot 转义,但在这个问题中我只对如何chdir("..") 转义技术在现代 Linux 系统上可以防止。为此,我正在寻找替代品chroot(2)系统调用。

我找到了2个解决方案:枢轴根MS_移动,但它们仅在/var/mychroot是挂载点时才起作用,因此如果/var/mychroot是文件系统中的子目录,它们就会失败/。在这种情况下还有其他解决方案吗?

我想避免使用技术LD_PRELOAD(因为LD_PRELOAD不影响静态链接的可执行文件),使用技术跟踪(2)(因为这样我就无法strace在 chroot 中运行,而且跟踪(2)正确处理非常棘手:进程会崩溃或挂起)和真正的虚拟化(例如 Xen 或 KVM 或 QEMU;因为性能开销和不太灵活的内存配置)。

回顾一下,我需要:

  • 的替代方案chroot(2)系统调用,
  • root 可以使用它限制以 root 身份运行的进程(EUID 0),
  • 到文件系统的子目录/
  • 这可以防止chdir("..") 转义技术,
  • 并且不使用LD_PRELOAD
  • 跟踪(2)或者
  • 虚拟化(例如 Xen、KVM 或 QEMU),
  • 它运行在现代 Linux 系统上,
  • 带有和未打补丁的内核。

它存在吗?

答案1

为了防止您提到的特定转义技术,您可以在被锁定后chdir("..")简单地放弃再次执行的能力。转义技术需要再次调用,因此阻止它足以阻止它工作。chroot(2)/var/mychrootchroot()

您可以使用 Linux 功能来做到这一点,只需删除CAP_SYS_CHROOT所需的功能chroot(2)即可。

例如:

outside# chroot /var/mychroot
inside# capsh --drop=cap_sys_chroot --
inside# ./escape_chroot
chroot(baz): Operation not permitted

(chroot 内的第二个提示来自于 生成的 shell capsh。您可以使用 使其运行另一个命令,例如capsh --drop=cap_sys_chroot -- -c 'exec ./escape_chroot'。)


但更好的技术是只使用pivot_root,因为它可以防止许多其他可能chroot(2)无法防止的攻击。

您提到它仅在/var/mychroot是安装点时才有效,但是您可以通过简单地将其绑定安装到自身中来使其成为安装点。

请注意,您需要创建一个挂载命名空间来用于pivot_root创建监狱,否则它将尝试更改文件系统中所有进程的根目录,这很可能不是您想要的......

所以整个顺序是:

outside# unshare -m
outside# mount --bind /var/mychroot /var/mychroot
outside# cd /var/mychroot
outside# mkdir old_root
outside# pivot_root . old_root
limbo# exec chroot .
inside# umount /old_root

(同样,这些命令中的许多命令都会生成新的 shell。unshare这样做,它本身也是如此chroot。您可以通过将命令作为额外参数传递来解决这些问题。在某些情况下,您可能希望传递sh -c '...'完整的脚本。)

此时,您位于pivot_root单独的挂载命名空间中的监狱内,事实上,这/var/mychroot只是原始根目录(而不是单独的设备或循环设备的挂载)并没有真正阻止其工作,感谢绑定安装到自身中。

运行转义代码,您将看到监狱按预期工作(即使转义代码声明不然):

inside# touch /inside_jail
inside# ./escape_chroot
Exploit seems to work. =)
inside# ls -ld /inside_jail /old_root
-rw-r--r--.  1 0 0    0 Jan  5 23:45 /inside_jail
dr-xr-xr-x. 20 0 0 4096 Jul  5 23:45 /old_root

正如你所看到的,仍在监狱内......利用代码有点天真,并假设只要操作(chrootchdir)成功,就足以逃脱监狱,但事实并非如此。 。

因此,考虑使用这种技术来创建一个监狱,该监狱优于chroot并且不需要使用 Linux 功能来阻止其中的操作(例如创建额外的chroots,这对于您实际尝试在监狱。)

答案2

它们仅在 /var/mychroot 是挂载点时才起作用,因此如果 /var/mychroot 只是 / 文件系统中的子目录,它们就会失败。

您可以将任何目录设为挂载点:mount --rbind /var/mychoot /var/mychoot

这里介绍了此步骤以及您需要的其他步骤:

如何使用 Linux 命名空间执行 chroot?

事实上我想阻止各种 chroot 逃逸

将以上内容与用户命名空间结合起来。

或者,seccompmount()例如,这就是 Docker 防止包含的进程调用的方式。 (当您第二次挂载块设备时,您将获得该文件系统的第二个视图,这或多或少算作一种转义)。复制 Docker 允许的系统调用列表 - root 有很多不同的转义方式。

https://docs.docker.com/engine/security/seccomp/

https://github.com/moby/moby/blob/master/profiles/seccomp/default.json

相关内容