Docker安全
Docker攻击面
容器一共有7个攻击面:Linux Kernel、Namespace/Cgroups/Aufs、Seccomp-bpf、Libs、Language VM、User Code、Container(Docker) engine
以容器逃逸为风险模型,提炼出3个攻击面:
1. Linux内核漏洞
2. 容器自身
3. 不安全部署(配置)
1. Linux内核漏洞
容器的内核与宿主内核共享,使用Namespace与Cgroups这两项技术使容器内的资源与宿主机隔离,所以Linux内核产生的漏洞能导致容器逃逸
攻击样例说明:
vDSO(Virtual Dynamic Shared Object)是内核为了减少内核与用户空间频繁切换,提高系统调用效率而设计的机制。它同时映射在内核空间以及每一个进程的虚拟内存中,包括那些以root权限运行的进程。通过调用那些不需要上下文切换(context switching)的系统调用可以加快这一步骤(定位vDSO)。vDSO在用户空间(userspace)映射为R/X,而在内核空间(kernelspace)则为R/W。这允许我们在内核空间修改它,接着在用户空间执行。又因为容器与宿主机内核共享,所以可以直接使用这项技术逃逸容器。
利用步骤如下:
1.获取vDSO地址,在新版的glibc中可以直接调用getauxval()函数获取。
2.通过vDSO地址找到clock_gettime()函数地址,检查是否可以hijack。
3.创建监听socket。
4.触发漏洞,Dirty CoW是由于内核内存管理系统实现CoW时产生的漏洞。通过条件竞争,把握好在恰当的时机,利用CoW的特性可以将文件的read-only映射为write。子进程不停的检查是否成功写入。父进程创建二个线程,ptrace_thread线程向vDSO写入shellcode。
madvise_thread线程释放vDSO映射空间,影响ptrace_thread线程CoW的过程,产生条件竞争,当条件触发就能写入成功。
5.执行shellcode,等待从宿主机返回root shell,成功后恢复vDSO原始数据。
2. 容器自身
docker架构图:
Docker本身由docker(docker client)
和dockerd(docker daemon)
组成。但从Docker 1.11开始,Docker不再是简单的通过docker dameon
来启动,而是集成许多组件,包括containerd
、runc
等等。
Docker client是docker的客户端程序,用于将用户请求发送给dockerd。dockerd实际调用的是containerd
的api
接口,containerd是dockerd
和runc
之间的一个中间交流组件,主要负责容器运行、镜像管理等。containerd向上为dockerd提供了gRPC
接口,使得dockerd屏蔽下面的结构变化,确保原有接口向下兼容;向下,通过containerd-shim
与run
c结合创建及运行容器。
CVE-2019-5736
runc – container breakout vulnerability:runc在使用文件系统描述符时存在漏洞,该漏洞可导致特权容器被利用,造成容器逃逸以及访问宿主机文件系统;攻击者也可以使用恶意镜像,或修改运行中的容器内的配置来利用此漏洞。
漏洞简介
runc是一个根据OCI(Open Container Initiative)标准创建并运行容器的CLI tool,目前Docker、Containerd和CRI-O等容器都运行在runc之上。
该漏洞允许恶意容器(以最少的用户交互)覆盖主机上的runc二进制文件,从而获得root权限在主机上执行代码。
漏洞可能影响通过受影响版本Docker部署的应用、虚拟主机、云服务器。K8s集群,含有受影响runc版本的Linux发行版等。
该漏洞允许恶意容器(以最少的用户交互)覆盖主机runc二进制文件,从而在主机上以root级别执行代码。
CVE-2019-14271
漏洞简介
docker cp
命令使用了docker-tar
辅助程序,该程序会以宿主机的root
权限加载容器的libnss
库,只要攻击者可以攻破容器,构造恶意的libnss
库,就能逃逸容器获取宿主机root
权限。
3. 不安全部署(配置)
在实际中,经常会遇到这种状况:不同的业务会根据自身业务需求有自己的一套配置,而这套配置并未得到有效的管控审计,使得内部环境变的复杂多样,无形之中又增加了许多风险点。譬如,最常见的:
特权容器或者以root权限运行容器。
不合理的Capability配置(权限过大的Capability)
特权模式
特权模式于版本0.6时被引入Docker,允许容器内的root拥有外部物理机root权限,而此前容器内root用户仅拥有外部物理机普通用户权限。
使用特权模式启动容器,可以获取大量设备文件访问权限。因为当管理员执行docker run --privileged
时,Docker容器将被允许访问主机上的所有设备,并可以执行mount命令进行挂载。
这种容器适于运行系统管理类的任务,它除了维护自己的文件系统和网络的隔离性外,*能全权访问主机的共享内存、设备、所有的 capability *等。
查找特权容器命令:
1 | docker ps --quiet -a | xargs docker inspect --format='{{.Id}} {{.Name}} {{.HostConfig.Privileged}}' |
Docker安全加固
对于安全实施准则,我们将其分为三个阶段:
1.攻击前:裁剪攻击面,减少对外暴露的攻击面(本文涉及的场景关键词:隔离)。
2.攻击时:降低攻击成功率(本文涉及的场景关键词:加固)。
3.攻击后:减少攻击成功后攻击者所能获取的有价值的信息、数据以及增加留后门难度等。
参考:
https://www.atjiang.com/limiting-risk-with-isolation-in-docker/
https://zhuanlan.zhihu.com/p/43586159