【Docker】Docker逃逸小结
前言
Docker自2013年发行开始,一直受到业界广泛的关注。
这篇文章将探讨Docker安全性相关的问题。
什么是容器?
容器的本质就是把系统中同一个业务目标服务
的相关进程组合在一起,放在一个namespace
中。
同一个namespace
中的进程能够互相通信,同时看不见其他namespace中的进程。
每个namespace拥有自己独立的主机名、进程ID、IPC、网络、文件系统、用户等资源
此外,为了限制namespace对物理资源的使用,要对进程能够使用的CPU、内存资源进行一定的限制,而使用Cgroup
技术就可以解决。
我们常说的4c4g容器
其实就是限制这个容器最多能使用4核计算资源和4G的内存空间
简而言之,Linux内核提供namespace完成隔离,Cgroup完成资源限制。namespace+Cgroup构成了容器的底层技术
容器的实现没有使用任何虚拟化的技术,而是一种隔离技术。可以简单的把docker理解成一种高级的chroot
Docker的安全机制
上文提到了,Docker使用的是隔离技术
,所以我们在容器内部使用的仍然是宿主机的内核、cpu与内存。这就可能导致一些安全问题的出现。
在讲述Docker可能存在的安全问题之前,先来探讨一下Docker是如何在最大程度上保证容器的安全性。
Docker使用到的安全机制有很多:
- Linux Capability
- AppArmor
- SELinux
- Seccomp
这里就简单的提一提Linux Capability
因为Docker默认会对User namespace不进行隔离,所以在docker内部cat /etc/passwd
的时候会查看到uid为0,也就是说Docker容器内部的root其实就是宿主机的root。
这时候就会有疑问了,既然是宿主机的root,应该是无所不能的,为什么很多服务都无法使用?并且有些命令会提示Permission denied
这个其实就是Linux Capability
实现的
自Linux 2.1开始,引入了capability的概念,它打破了操作系统中超级用户和普通用户的概念,普通用户通过设置capability也可以做到超级用户才能干的事情
Linux Capability一共有38钟,docker默认开启了14种,这样就有效的避免了很多安全问题
如果开启docker使用了--privileged=true
,那么其实就是开启了所有的capability
Docker逃逸
docker逃逸的类型无非下面三种:
- 配置不当
- Docker软件的漏洞
- 内核漏洞
1.特权模式
我们在上面讲到,特权模式将capability全开了,那么就存在挂载权限。
可以通过mount的方式将宿主机的根目录挂载到容器中,这样就可以通过容器对宿主机的文件进行读写。
这里用一个ubuntu20.04的容器来进行说明
- 以特权模式开启ubuntu20.04容器,执行/bin/bash
- 执行fdisk -l 查看挂载情况
- cd进入/dev 查看挂载情况
- 在/dev创建一个文件夹 mkdir
test114
- 将/dev/sdc挂载到刚刚创建的test114上
- 可以查看宿主机的文件,同时可以修改
- 创建一个test114文件
- 回到宿主机查看,发现确实有这个新增的文件,并且文件所有者就是root
2.--cap-add=SYS_ADMIN
使用--cap-add=SYS_ADMIN
的参数,可以让docker容器内部使用mount和unmount,可以实现上述一样的效果
3.挂载了Docker.sock
Docker使用的架构是C/S架构,我们使用的docker指令,docker就是client,而server端是由docker daemon完成的,两者之间的通信方式有如下三种:
- unix:///var/run/docker.sock
- tcp://host:port
- fd://socketfd
docker默认使用docker.sock进行通新,当容器中进程与Docker守护进程进行通信的时候,容器本身需要挂载unix://var/run/docker.sock文件
本质来说,如果能够访问docker socket或者连接https的api,那么就可以执行docker服务能够执行的任何命令。
所以如果容器中有能够访问docker服务端的能力,就可以完成docker逃逸,具体操作就是:
- container内部安装docker.io(客户端),通过容器内部存在的docker.sock或者api与宿主机的server进行交互
- 让宿主机server以特权模式开一个容器,进入该容器,执行任意命令(或者直接使用-v参数进行挂载根目录的操作)
这里就拿一道最近的比塞题来讲解吧,2022年的Real World体验赛的Be-a-Docker-Escaper
题目给出的Dockerfile中存在如下一句话:
docker run -i -m 128m -v /var/run/docker.sock:/s ubuntu # You are here!
非常明显将/var/run/docker.sock
挂载到了容器的/s
下
执行如下操作即可访问宿主机中的flag:
apt update
apt install docker.io
mkdir /test114
docker -H unix:///s/docker.sock run -v /:/test114 -i ubuntu /bin/bash
cd /test114
cat flag
4.脏牛漏洞(内核漏洞)
Dirty Cow(CVE-2016-5195)是Linux内核中的权限提升漏洞,源于Linux内核的内存子系统在处理写入时拷贝(copy-on-write, Cow)存在竞争条件(race condition),允许恶意用户提权获取其他只读内存映射的写访问权限。
已经有人将环境打包成了一个docker镜像,可以直接复现
gebl/dirtycow-docker-vdso (github.com)
5.runc (cve-2019-5736)
poc地址 Frichetten/CVE-2019-5736-PoC: PoC for CVE-2019-5736 (github.com)