安全似乎落后于Docker阵营在其他方面的发展步伐。虽然越来越多的企业在数据中心使用Docker,但管理员们用来保护容器的技术却完全是慢慢站稳脚跟。在许多情况下,正是当初让Docker大受欢迎的功能特性恰恰也暴露了安全漏洞。
Docker网站称赞其容器是即刻奏效的解决方案
什么是没有隔离的内核?Docker依赖Linux内核的功能:建立相互隔离的环境(应用程序在里面运行)。这些容器很精简,因为它们共享同一内核,却在不同的运行时环境中执行,这归功于控制组(cgroup)和命名空间,它们定义了容器可以使用哪些资源。与此同时,容器本身只能看到某些进程和网络功能。
虽然攻击者难以从一个被劫持的虚拟机与主机的内核进行交互,但容器隔离并不提供同样的防御。除了/sys和/proc外,攻击者还照样可以进入内核的关键子系统,比如SELinux和控制组,这意味着攻击者有可能避开主机的安全功能特性。与此同时,容器使用与主机系统同样的用户命名空间。换句话说,如果进程以根权限在容器中运行,它与内核或挂载的文件系统交互时,保留这些权限。因而,管理员还是别以根权限在容器中运行软件为妙;实际上,很少需要这样。
风险:Docker的守护进程然而,Docker守护进程需要根权限。它管理主机上的容器,需要与提供隔离环境的内核进行对话。与守护进程进行交互的用户因而被授予了访问系统的权限。如果主机托管服务提供商通过Web界面将容器作为一个自助服务选项来提供,这种情形会来得尤其严重。
虽然使用docker群组是个办法,但不太可能改善安全,因为群组成员可以构建容器;而在容器中,首先可以运行根外壳,其次可以挂载主机的根文件系统。这里的唯一办法就是,严格监管对Docker服务的访问,避免不需要的权限升级。
此外,Docker的守护进程可以通过HTTP(S),借助REST API进行联系。如果你使用这项功能,就需要限制只由可信赖网络才可以访问API,或者通过SSL客户端证书或之类的机制来限制访问。
对策新版本的Docker随带减小上述攻击场景带来的影响的功能特性。Docker以只读方式挂载/sys文件系统和/proc中的重要文件。容器无法写入到它们,因而防止容器中的权限进程操纵主机系统。
内核将根权限细分成了几项功能,然后将这些功能逐个分配给了进程。默认情况下,Docker阻止重要功能,防止容器中的权限进程为非作歹。这些功能包括网络配置、装入内核模块的功能或者访问音频子系统。如果某个特殊的应用程序需要被阻止的功能,Docker允许这些功能供某个容器使用。
SELinux局限性SELinux是一种安全框架,它给每个文件和每个进程分配了多部分标签(multipart label)。策略定义了哪个进程标签可以访问哪个文件标签。Docker支持两个变种:类型强制(type enforcement)和多类别安全(MCS)。
类型强制限制了容器对主机文件系统的访问。所有容器进程都以同一种类型来运行,这样就可以访问容器中的文件和许多主机系统文件,但是又可以防止访问主机上的大多数文件夹(即/var、/root和/home)。
如果只使用类型强制,容器就能够轻松访问其他容器中的数据。归功于MCS,容器启动时,SELinux为容器分配了随机的MCS标签;Docker守护进程用这个标签标记容器中的所有文件,而内核可防止使用不同MCS标签的进程访问容器中的文件。
在许多企业,SELinux已被认为是一项不需要的功能特性,也是管理员们喜欢禁用的一项特性。然而,Docker容器的安全依赖安全虚拟化(sVirt)之类的功能特性。在几乎没有其他应用程序帮助的情况下,单单sVirt就足以防止来自其他容器的用户读取你的文件。
未来就未来而言,Docker开发人员在计划增强容器的安全性和隔离性。三项功能特性会助一臂之力,包括用户命名空间、Seccomp,以及基于角色的访问控制(RBAC),加强对Docker守护进程的访问。
用户命名空间获得了优先权。Docker将来自容器的用户ID与其他主机的ID对应起来。其想法是大大限制攻击属于根目录的文件的能力。
由于所有容器都与同一个内核对话,内核功能方面的一个错误对主机和容器之间的边界以及对容器本身之间的边界来说都是致命的。来自谷歌的Seccomp可防止进程对特定系统调用的访问。虽然进程使用系统调用来访问内核,但在600个可用调用中大多数很少用到。要是没有这些调用,有望减小潜在的攻击面。Daniel Walsh在红帽公司从事容器安全工作。他认为,开发人员有望将可调用系统调用的数量最多减少50%。