我在与/
相同的文件系统上有一个目录D1
,并且已经以sudo chroot /var/mychroot /prog
的形式启动了程序/var/mychroot/prog
,因此该程序以EUID 0的形式运行。
如果程序执行(“.”)逃逸技术,那么它能够转义chroot并查看/
中的所有内容。(我已经在Linux4.18上验证了这一点。)
我想阻止这样的逃跑。事实上,我想防止所有类型的chroot逃逸,但在这个问题上,我只对如何在现代Linux系统上防止(“.”)逃逸技术感兴趣。为此,我正在寻找chroot(2)系统调用的替代方案。
这个案子还有别的解决办法吗?
我希望避免使用LD_PRELOAD
的技术(因为LD_PRELOAD
不影响静态链接的可执行文件)、使用ptrace(2)的技术(因为这样我就无法在chroot中运行strace
,而且ptrace(2)也很难正确:进程会崩溃或挂起)和真正的虚拟化(例如Xen或KVM或QEMU;因为性能开销和内存配置不那么灵活)。
回顾一下,我需要:
/
文件系统的子目录,LD_PRELOAD
或它存在吗?
发布于 2019-01-05 07:51:19
为了防止您提到的特定chdir("..")
转义技术,您可以简单地放弃再次执行chroot(2)
的能力,一旦您自己被推荐到/var/mychroot
。转义技术需要对chroot()
进行另一次调用,因此阻塞就足以阻止它工作。
您可以使用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内部的第二个提示符来自capsh
生成的shell。您可以让它运行另一个命令,例如,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
如你所见,还在监狱里..。利用该漏洞的代码有点天真,并假设只要操作(chroot
、chdir
)成功,就足以逃脱牢狱之灾。
因此,考虑使用这种技术创建一个比chroot
优越且不需要使用Linux功能来阻止内部操作的监狱(例如创建额外的chroot
s,这对于您实际上试图在监狱中运行的操作可能是有用的或必需的)。
发布于 2019-01-05 10:14:01
它们只能在/var/mychroot是一个挂载点的情况下工作,所以如果/var/mychroot只是/ fail系统中的一个子目录,它们就会失败。
您可以将任何目录设置为挂载点:mount --rbind /var/mychoot /var/mychoot
。
这一步--以及您需要的其他步骤--将在这里讨论:
事实上,我想要防止各种颜色的逃逸。
将上述内容与用户命名空间相结合。
或者,seccomp
.例如,这就是Docker阻止包含的进程调用mount()
的方式。(当您第二次挂载块设备时,您将得到该文件系统的第二个视图,该视图或多或少可以算作转义)。复制Docker允许的syscalls - root列表有很多不同的转义方式。
https://docs.docker.com/engine/security/seccomp/
https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
https://unix.stackexchange.com/questions/492607
复制相似问题