使用 chroot 建立沙盒环境
chroot 提供了更改当前进程及其子进程的可见根目录的操作,运行在此隔离环境中的应用程序无法访问新的目录树之外的文件和命令。这样的隔离环境称作 chroot 监狱(chroot jail)。通常,chroot 用于建立沙盒环境,以及在单用户模式或救援模式下进行系统维护或重置密码等操作。
更多资料参见 chroot - ArchWiki
Usage
chroot
命令的语法如下:
chroot [option] newroot [command [args]] # 以 ~/tmp 为新的根目录,执行 /bin/bash # 这里 /bin/bash 是新目录下的路径 chroot ~/tmp /bin/bash
资源准备
显然,仅仅使用 mkdir
命令创建一个空目录就想在其中执行 chroot
进程是不可行的,因为我们还没有在新的目录下准备必要的资源。首先我们需要把 shell
工具装入该目录——当然,如果只是运行某一条命令,确实不必为其准备终端工具。此外,为了顺利执行大部分终端操作,我们还应将 /usr/bin
目录下的必要文件及其依赖库复制到新的根目录下,通常包括 ls
/mkdir
/mv
/cp
等基本命令和其他一些可能需要用到的命令。
mkdir ~/tmp/{bin,lib,lib64} cp /bin/* ~/tmp/bin -r cp /lib/* ~/tmp/lib -r cp /lib64/* ~/tmp/lib -r
除此之外,在/dev
目录下的一些必要节点有时也需要手动建立:
mkdir ~/tmp/dev cd ~/tmp/dev mknod -m 666 null c 1 3 mknod -m 666 tty c 5 0 mknod -m 666 zero c 1 5 mknod -m 666 random c 1 8
注:
- 要查看一个可执行文件的依赖库,执行
ldd
命令,如ldd /bin/sh
。- 请结合使用
chown
/chmod
命令保证这些文件和目录的所属和权限与原文件系统一致。- 这里不可使用软链接,因为在新的根目录下,软链接无法定位到外部原文件。
- 除了用于本地主机的维护外,
chroot
监狱还可用于限制SSH
用户根目录。
例题
题目来源:USTC Hackergame 2019
有一天,C 同学做了一个梦,他竟然搬进了大房子,只是似乎有些地方 C 同学不太满意……
注意:
- 此题考察的是对于 Linux 基础知识的掌握。尽管可以,但不建议使用逆向工程的方式完成。
- 在根目录(
/
)下的文件夹对 Linux 系统的运行十分重要,请不要为了完成此题目删除自己的/usr
,/bin
等文件夹!
这里我以 Alpine Linux 为例,简要介绍此题的一种解法。
下载题目源文件并简要分析
结合所给提示,使用 curl
/wget
等工具下载题目附件,用 readelf
/objdump
等工具分析得知该文件是一个 Unix 可执行文件,OK 先给上可执行权限并运行一下:
# 下载 wget http://url/IWantAHome # 查看 elf 文件头 readelf -h IWantAHome # 添加可执行权限 chmod +x IWantAHome # 执行 ./IWantAHome
输出:
$ ./IWantAHome I just want a home. Please do what I say and I will give you a flag Make sure I am running on Linux(Unix). I want these directories in / : [/Kitchen /Lavatory /Bedroom /Living_Room] Oh I can not find /Kitchen ,goodbye.
看来要创建这些目录,创建完再运行:
$ mkdir /Kitchen /Lavatory /Bedroom /Living_Room $ ./IWantAHome I just want a home. Please do what I say and I will give you a flag Make sure I am running on Linux(Unix). I want these directories in / : [/Kitchen /Lavatory /Bedroom /Living_Room] Thanks, I find these directories. I hate these directories [/home /root /boot /proc /sys /etc /bin] , Please delete them all! Oh I found /home ,goodbye.
得,这是想让我删系统呢。
建立沙盒
删系统?抱歉,今天不行!我们直接挑个好地方建立起一个 newroot
目录,比如在 /root
下建立 tmp
,然后先将 /bin
下的文件复制进 /root/tmp
中(注,这里要求删除 /bin
目录,故复制到 tmp/b
目录下):
# 创建目录 mkdir /root/tmp mkdir /root/tmp/b # 复制文件 cp /bin/* /root/tmp/b cp IWantAHome /root/tmp # 查看 /bin/sh 的依赖 ldd /bin/sh # 复制依赖库 cp /lib /root/tmp -r # 顺便把刚才建立的 Kitchen 等目录移进去 mv /Kitchen /Lavatory /Bedroom /Living_Room tmp
进入沙盒环境并再次执行文件:
# 进入 chroot 环境 chroot /root/tmp /b/sh # 更改环境变量 export HOME=/ export PATH=/b # 执行文件 ./IWantAHome
这时程序输出表示要在 /Bedroom/Microphone
中写入文件并从 /Bedroom/Headset
中读出,这个容易,新建其中一个文件,然后在另一个位置建立一个链接就行。
# 建立新文件 touch /Bedroom/Microphone # 建立符号链接(硬链接也可) ln -s /Bedroom/Microphone /Bedroom/Headset
写时间脚本
再运行程序,提示要从 /Living_Room/Clock
中读取到 20:15:30
形式的北京时间,那只好写一个后台脚本不断向文件中写入当前时间……所以我选择先退出 chroot
环境(亦可直接在 chroot
进程内执行),先设置一下时区。
# 安装 tzdata 包以提供时区信息 apk add tzdata # 在 /etc 下建立 /usr/share/zoneinfo/Asia/Shanghai 的链接 ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 查看时间是否准确(如不准确,使用 date -s "20:15:30" 命令更改) date # 新建 time.sh 文件并赋予可执行权限 touch time.sh && chmod +x time.sh # 编辑 time.sh vi time.sh
写入以下脚本:
#!/bin/sh while true do date +"%H:%M:%S" > /root/tmp/Living_Room/Clock sleep 0.5 done
并让它在后台运行:
./time.sh &
重新进入 chroot
环境,设置好环境变量,再次运行 IWantAHome
:
$ ./IWantAHome # 略去部分输出 Time is important, I need a clock in living_room I will read Beijing time (eg: '20:15:30') in /Living_Room/Clock Good, the clock works well. It is late, tell me how to sleep 10 seconds in shell >
要求输入 “sleep 10 seconds” 的命令……嗯,输入 sleep 10
。这里有两个点,一是 sleep
命令并不一定需要用 shell
指令,可以自己写一个定时的程序;二是这里要用到一个 /dev/null
的设备,这个设备可以用 mknod -m 666 /dev/null c 1 3
创建,也可以只建立一个普通文件——反正附件程序不检查。
最终输出
完成这些操作后,再执行 IWantAHoome
:
$ ./IWantAHome I just want a home. Please do what I say and I will give you a flag Make sure I am running on Linux(Unix). I want these directories in / : [/Kitchen /Lavatory /Bedroom /Living_Room] Thanks, I find these directories. I hate these directories [/home /root /boot /proc /sys /etc /bin] , Please delete them all! Well done. Now I want a telephone in Bedroom I will write something to /Bedroom/Microphone and read the same thing in /Bedroom/Headset Good, telephone works well. Time is important, I need a clock in living_room I will read Beijing time (eg: '20:15:30') in /Living_Room/Clock Good, the clock works well. It is late, tell me how to sleep 10 seconds in shell > sleep 10 command is:'sleep 10' I slept for 10.00281629s flag{I_am_happy_now}
至此,flag 到手!