type
status
date
slug
summary
tags
category
icon
password
漏洞环境
环境部署
漏洞影响版本
- Docker < 19.03.1
拉一个 alpine 镜像
这里如果用 ubuntu 镜像会出现问题
不过后面利用的时候好像 ubuntu 镜像又好了,很神奇…
漏洞描述
The vulnerability can be exploited, provided that a container has been compromised by a previous attack (e.g. through any other vulnerability, leaked secrets, etc.), or when a user runs a malicious container image from an untrusted source (registry or other). If the user then executes the vulnerable cp command to copy files out of the compromised container, the attacker can escape and take full root control of the host and all other containers in it.
前置知识
docker cp
命令是用来在容器和宿主机之间拷贝文件的,比如把容器中的 /var/logs
目录拷贝到本机这里在容器内通过
dd
在 /var/log
新建了个大文件,以便于捕捉复制文件时的进程。如下,当我们执行 docker cp
时,通过 ps 看到运行了一个 docker-tar
的进程从容器内打包文件/var/lib/docker/overlay2/3f5442ab960e56e8e34cfda288b5ec4d313b51b53319e4671a8d8add0c397369/merged/
为容器文件系统根目录,var/log
即为日志目录通过查看进程的根目录发现
ls -l /proc/29989/root
,执行 docker-tar
时会 chroot 至容器目录,因为这可以避免一些恶意软链接文件至宿主问题。尽管 chroot 至容器可以避免恶意软链接,但通过CVE-2019-14271 仍可进行逃逸漏洞分析
Docker主要是通过Go编写,存在 漏洞Docker版本通过Go 1.11 编译,这个版本一些包含嵌入式C代码(cgo)会在运行时动态加载共享库。
docker-tar
使用了 net 和 os/user 包,它们在运行时都会加载 libnss_*.so
动态链接库,本来是没有问题的,因为是加载宿主机上的 .so
,但打包容器内的文件时,会通过 chroot 进入容器内,导致加载了容器内的 .so
,但容器内的 .so
是可被篡改的,而运行打包命令是宿主机环境,从而导致逃逸。docker-tar
调用栈经分析我们需要构造一个恶意的
.so
库,用于加载我们的恶意代码。报错信息写的是加载 libnss_files.so.2
那我们就改这库的源码。查阅文档得知可通过构造方法让进程在加载动态链接库时先初始化构造函数,也就是说 docker-tar
执行时会动态加载我们的恶意库中的恶意函数,简化后的代码如下此函数通过检测
/proc
目录是否为空来判断自己是否运行在 docker-tar
上下文中,如为空则是运行在 docker-tar
上下文中,如非空则为其他正常的容器进程加载这个动态链接库,因为 /proc
上的procfs挂载只存在于容器挂载上下文中。如果是通过
docker-tar
调用的此库,先把恶意库恢复为原来的,防止其他进程再一次出发我们的脚本,其中 /breakout
是我们要运行的shell脚本,方便我们改要运行的命令据说漏洞发现是由一个外国老哥遇到一个docker cp 复制文件问题引起的https://github.com/moby/moby/issues/39449 ,报错信息写着加载到了 libnss_files.so.2 文件
漏洞利用
执行
docker cp
后即触发漏洞主要有两种方式- 拉取一个攻击者构造恶意
libnss_*.so
动态链接库的容器
- 攻击者获取到容器内一定权限,可以替换
libnss_*.so
漏洞修复
在 chrootarchive 包初始化时先加载
libnss
动态链接库,因为 user
和 net
这两个包的方法会加载到,只要调用了, 这时加载是从宿主机加载 libnss
动态链接库,宿主机的库从容器内无法更改,从而避免逃逸问题。关于漏洞修复 ssst0n3 师傅分析的更为深入,膜拜