Docker学习与实践 - 安全篇
概述
在多数情况下,启动Docker容器时都以root用户权限在运行,那么如果有ROOT权限可以做什么呢?当然可以做很多的事情,比如:访问所有信息、修改任何内容、关闭机器、结束进程以及安装各种软件等。
容器的安全性问题的根源在于容器和宿主机共享内核,如果容器里的应用导致Linux内核崩溃,那么整个系统可能都会崩溃。与虚拟机是不同的,虚拟机并没有与主机共享内核,虚拟机崩溃一般不会导致宿主机崩溃。
Docker的安全性主要体现在如下几个方面:
- Docker容器安全性,如:是否会危害到宿主机或其他容器;
- 镜像的安全性,如:如何确保下载的镜像是可信的、未被篡改过的;
- Docker守护进程安全性,如:如何确保发送给Daemon的命令是由可信用户发起的。
接下来会通过一些简单的操作来验证一些安全问题,同时会提出一些安全上的实践和原则。
Docker访问主机系统
首先来验证一下,能否访问主机上的存储密码相关的 /etc/shadow 文件?
123456789101112$ cat /etc/shadow # 使用普通用户访问cat: /etc/shadow: Permission denied$ who am i; groups; # 查看当前的用户和组vagrant pts/0 (10.0.2.2)vagrant docker$ sudo cat /etc/shadow # 使用管理员用户访问root:$6$HmunRCSU$YXNgf...bnj2AVtjAFfmh0:16744:0:99999:7:::daemon:*:16744:0:99999:7:::vagrant:$6$55jH0QFsuLa...vGb8lH/9jQy4r0:16744:0:99999:7:::...再来验证一下,能否在 Docker 容器中访问
/etc/shadow
文件呢?12345$ docker run -v /:/hostfs busybox cat /hostfs/etc/shadowroot:$6$HmunRCSU$YXNgf...bnj2AVtjAFfmh0:16744:0:99999:7:::daemon:*:16744:0:99999:7:::vagrant:$6$55jH0QFsuLa...vGb8lH/9jQy4r0:16744:0:99999:7:::...可以看到,在容器中是可以访问宿主机上只有root用户才能访问的密码敏感文件的,当然也是可以访问其他root权限的文件的。
再来看一下,能否在Docker容器中修改主机文件系统?
123456$ ls / | grep threat$ docker run -it -v /:/hostfs busybox touch /hostfs/threat-on-the-way$ ls / | grep threatls / | grep threatthreat-on-the-way可以看到,在 Docker 容器中,能够在宿主机根目录创建文件,并且可以修改主机文件系统。更严重的时,如果是 Privileged 容器,即在运行容器时指定
--privileged=true
参数,则能够允许容器所有设备执行任意操作,能够读写内核内存/proc/kcore
,使用参数--net=host
可以嗅探主机所有网络流量。最后,来查看一下 Docker 容器和
Metadata
存储在哪儿?123456789101112$ ls /var/lib/dockeraufs containers graph linkgraph.db network repositories-aufs tmp trust volumes$ cd /var/lib/docker/; sudo du --max-depth=14 ./trust88 ./network5246812 ./aufs4 ./tmp579872 ./volumes1900 ./containers11740 ./graph5840444 .运行态容器默认都是使用
/var/docker/lib
目录,容器内部写日志、产生运行时数据等都会影响该目录,并且产生的文件越来越多,占用空间越来越大,因此需要定期清理无用的镜像和容器,应为Docker挂载点/var/docker/lib
创建单独的分区,最好是SSD盘。
另外,最推荐使用供应商最支持的存储驱动程序,aufs是唯一的允许容器共享执行文件的存储驱动,但可能会导致严重的内核崩溃。
Docker安全最佳实践
为了保证 Docker 安全性,需要在各方面遵循一些实践和原则,包括宿主机方面、Docker守护进程、使用镜像以及容器运行方面。
在宿主机方面
- 保持内核及时更新,防止黑客利用未修复的漏洞进行攻击
- 增强主机安全保护,如果主机不安全了,容器也就谈不上安全了
- 保持Docker及时更新,特别要关注Docker安全相关方面的更新
守护进程方面
- 只允许受信用户控制Docker守护进程,保证与Daemon的连接是可信的
- 不使用不受信的镜像仓库,因为镜像可能会被篡改过
- 必要时请为Docker守护进程应用 TLS 认证网络
- 限制容器之间的网络通信,如果两个容器之间没有通信的必要就限制其网络通信功能
使用镜像方面
- 在Dockerfile中为容器创建一个非root用户,具体方法可以参阅 文章
- 以非root用户运行容器进程,最大程度控制用户的权限范围
- 只使用受信的基础镜像,可由最小基础镜像开始(Busybox, Alpine),最好是建立本地仓库镜像
- 仅安装必要的包,因为可能有些包会有漏洞,一定程度上降低风险
- 重新构建镜像时需要包含安全补丁,防止黑客利用漏洞实施攻击
容器运行时方面
- 不要到产品环境中使用任何开发者工具(boot2docker, kinematic)
- 限制容器使用Linux内核能力和资源使用,为守护进程设置受限的控制资源权限(–ulimit)
- 不要使用 Privileged 容器,如果使用
--privileged
参数将授予容器与主机几乎相同的权限 - 指定容器重启策略为
on-failure
,重启策略有四种,详细可以参阅 Restart policies - 使用强制权限控制系统 AppArmor 和 Linux安全增强工具 SELinux 保证额外的安全层
小结
Docker安全性主要体现在容器安全性、镜像安全性和守护进程安全性,可以看到在Docker容器中能够访问宿主机的高权限资源,如果管理和使用不得当,将造成严重的后果,因此,在平时使用Docker时应在多方面遵循一些最佳实践和原则,包括宿主机方面、Docker守护进程、使用镜像以及容器运行等方面,尽可能保证 Docker 安全性。
「特此声明: 本文大部分内容译自内部培训资料」
References