0x00 前言
最近网鼎杯青龙组做到了一道chroot逃逸的题目,正好整理一下它逃逸的原理。
0x01 逃逸利用
通常来说,chroot一般有两个含义,chroot(1)是/usr/bin/chroot, chroot(2)是glibc中的一个函数。
chroot(1)
chroot - run command or interactive shell with special root directory
chroot [OPTION] NEWROOT [COMMAND [ARG]…]
chroot(2)
chroot - change root directory
int chroot(const char *path);
chroot主要的功能是改变根目录,之前是在ctf出题时会将/home/ctf目录chroot成为根目录,实现与我们docker的文件系统隔离,提供一个安全的靶场环境。在模拟运行固件的时候,也经常会将当前文件系统的目录chroot为根目录,这样才能找到固件所需库的路径。
但chroot是一个不安全的feature,容易被逃逸出来,这里有一个逃逸用的[工具](earthquake/chw00t: chw00t - Unices chroot breaking tool (github.com))
里面也包含了一些逃逸常用的方法
网鼎杯青龙组exp
1 | from pwn import * |
0x02 chroot实现
keys_chroot源码
via: https://elixir.bootlin.com/linux/v5.6/source/fs/open.c#L506
chroot运行在内核,会调用系统函数ksys_chroot函数
1 | int ksys_chroot(const char __user *filename) |
set_fs_root
主要函数,就是在这个函数里修改了程序的 “根目录”
via: https://elixir.bootlin.com/linux/v5.6/source/fs/fs_struct.c#L15
先来看一下 fs_struct
1 | struct fs_struct { |
1 | /* |
struct path
via: https://elixir.bootlin.com/linux/v5.6/source/include/linux/path.h#L8
1 | struct path { |
struct vfsmount
描述独立文件系统的挂载信息,每个不同的挂载点对应一个独立的 vfsmount
结构,属于同一文件系统的所有目录和文件隶属同一 vfsmount
该 vfsmount
结构对应于该文件系统顶层目录,即挂载目录
via: https://elixir.bootlin.com/linux/v5.6/source/include/linux/mount.h#L68
1 | struct vfsmount { |
###
总结
其实 chroot 修改了进程的 root 目录的核心操作就是修改了 进程 的 task_struct -> fs -> root
通过文件名去解析 文件夹 对应的path
结构,存在patch
变量里面,然后权限检查,再然后把path
传进set_fs_root
函数
1 | fs->root = *path; |
修改了root,这样进程就认为 filename
是根目录,因为 fs->root
存的是 filename
目录的 path
结构
但我们可以发现,它只改变了root
,但是没有改变cwd
chroot jailbreak 原理分析
根据上文源码可以发现,我们只改变了root
,但是没有改变cwd
chroot()
不改变工作目录。因此通常在调用chroot()
之后会紧跟chdir("/")
,把工作目录设定到新的root;否则仍可使用工作目录访问jail外的文件。只是之后访问jail外的文件不可以用绝对路径了,因为root目录还在jail里。- 可以使用jail外文件的文件描述符脱离jail,使用
fchdir()
即可改变工作目录到jail外。如果是特权进程的话(精确地,指拥有CAP_SYS_CHROOT
权限),还可以在fchdir()
后使用chroot(".")
以把root目录设置到jail外。倘若多chdir("..")
几次,可以回到原先的root目录。 - Unix domain socket提供了进程间传递文件描述符的方法。限定在chroot jail内的进程可以从外部获取文件描述符,之后即可
fchdir()
使工作目录脱离jail。
下面是一个例子
1 |
|
0x03 参考
清华校赛THUCTF2019 之 固若金汤 | Clang裁缝店 (xuanxuanblingbling.github.io)