Docker Hub中超过30%的官方镜像包含高安全风险
Docker Hub 是一个供Docker开发者用来上传/下载容器镜像的地方。为了理解其应对安全风险的能力如何,我们对其中的镜像进行了一次细致的研究。结果我们惊奇的发现,超过三成的官方仓库包含的镜像疑有高度的安全风险(如:Shellshock,Heartbleed, Poodle等)。对于普通的镜像,即哪些被docker用户上传的,没有经过任何权威机构验证过的镜像,这个数字达到了40%,样本的错误大约在3%。
[图:多姿多彩的容器,图片来源自VSMagazine]
为了开展这次研究,我们下载了Docker Hub中的的镜像,然后分析其中的软件包和其版本。然后我们使用来自Mitre,NVD(美国国家漏洞数据库)和Linux发行版自己特定的数据库来分析哪些镜像易于收到攻击。我们开发一个开源的工具 Banyan Collector并且使用使用一个叫做Banyan Insights的服务来生成这个研究中的数据。
尽管我们的分析是基于公共的Docker Hub进行的,我们预估这结果跟那些使用私有容器注册中心的企业会类似。企业通常会不断基于那些口碑较好镜像来部署容器,依赖这些镜像的周期更新来获取最新的软件包。尽管有这些措施,企业仍然有漏洞的威胁;更加强力的管理错误加上实时的监控对于保证安全必不可少。
在本文的剩余部分,我们简单的从高层次介绍下安全漏洞是如何分类,描述根据分析Docker Hub上官方和普通镜像中漏洞得到的结果,然后讨论下这份研究对于运维管理的意义。
安全漏洞的指定和分类
Mitre作为一个不为盈利的机构,指定并维护一份CVE(常见安全漏洞和威胁)的列表,每一个CVE描述了在广泛发布的的软件爱呢中的漏洞。由美国政府NVD数据库列出了每一个CVE的影响,包含器波及的软件和响应的修复措施(或者尚未修复的)。每一个Linux发行版也都维护了一个发行版特定的影响和提供修复该漏洞的软件包版本。
每一个漏洞都会每NVD和Linux的发行版指定一个评分。分数的范围从0到10,7.0到10.0属于高危漏洞,4.0-6.9之间的中危漏洞,0-3.9的术语低危漏洞。这个分类考虑了一系列因素,包括需要攻破系统所需要的复杂度(复杂度越低,分数越高)和该漏洞可能会造成的影响(影响越大,分值越高)。下面是一些例子:
- 高危漏洞:如:ShellShock(bash),Heartbleed(OpenSSL)
- 中危漏洞:如:Poodle(OpenSSL)
- 低危漏洞:如内存中数组的内存的分配可能会导致整形溢出
把漏洞分到高中低漏洞中的做法带有主观性,可能被一些公司根据自己的情况来重新分类。并且,NVD指定的分值可能跟Linux发行版中的分支不一致,并且可能会随着时间而更改。我们的研究使用该漏洞被Ubuntu和CentOS指定的分值,但是对与Debian我们直接使用NVD中分值,因为我们找不到任何关于Debian对与漏洞分类的好的数据源。我们对Docker Hub在2015的5月20日做了一个快照,然后进行分析。我们也试了一下其他日子,得出的结论查十分相近。
对于Docker Hub中官方仓库的评估
Docker维护着一个官方的仓库的列表,为软件厂商和机构(如Canonical,Debian,Redhat等)提供了一个即时更新他们最新容器镜像的渠道。官方仓库可以从他们的路径体现出来,他们的路径都有‘library’。举几个例子: library/ubuntu
, library/redis
等。Docker Hub包含大约75个官方的仓库(在我们写这篇文章的时候),大概包含月1600的不同的标签指向大约960个不同的镜像。
[图一:官方有漏洞的镜像]
图一展示了分析了Docker Hub上所有官方的镜像的得出的主要结果。超过1/3的镜像有高危漏洞,接近2/3的有高或中危漏洞。这些统计数据让人不能平静,因为这些镜像中一些也是下载量最多的镜像(一些有几十万的下载量)。
如果我们只看今年创建的镜像,有高危漏洞的镜像的比例仍然超过1/3,但是含有高和中危漏洞的镜像接近了75%。换句话说,每四个今年创建的镜像有三个包含有相对容易被利用的漏洞,并且其潜在的影响十分的大。
如果我们将范围缩小到哪些标注了lastest(最新)的镜像,这比例分别下降到了23%和47%,这比例显然还是很高。这更小的数字说明,docker的用户和维护者们,倾向于将镜像保持到最新,但是老一些的镜像却被忽略了;创建容器的高量,容易让老的镜在更新的时候让老的更新的时候被忽略。
为了理解这些漏洞,特别是排名靠前的,我们做了一个详细的影响Docker Hub的镜像漏洞的分析:
[图二: Docker Hub官方镜像中有高危漏洞的镜像]
图二展示了该分析的主要结果,并且表一列举了跟这些软件包相关的主要的CVE。最近发布的存在于mercuarial的漏洞在很大一部分的镜像中都有(大约20%)。高调的OpenSSL漏洞如Heartbleed和Poodle,在进10%的官方镜像中存在。一些镜像还包含bash的ShellShock(如Centos5.11)漏洞,这个漏洞在7个月前就被发布了。即时一些机构不使用这些包,但是如果不手动将这些包从容器中移除掉也会成为恶意攻击的羔羊。
对于Docker Hub中普通仓库的评估
除了一些官方的仓库,Docker Hub包含了一大部普通仓库(在写本文的时候大约有95000个),并且有数十万不一样的镜像。对于我们实验,我们随机选择了1700个镜像然后分析他们的内容(误差约百分之三)。
[图三:有漏洞的普通镜像]
图三显示了在分析了普通镜像后得到的主要结果。大体上,漏洞的出现概率比官方镜像的相比大的多。这个结果合乎预期因为目前尚没有错误可以在将镜像上传到Docker Hub前过滤检查这些普通的镜像。
大约40%的普通镜像有高危的漏洞。即时我们只是看今年创建的镜像,并且只看哪些有latest标签的,包含漏洞威胁的镜像的比例仍然在30-40%之前徘徊。如果我们包含哪些含有中危漏洞的镜像,比例会迅速升到70%以上,不管哪个时间段如此。尽管你可能会说,这些镜像比起官方镜像下载次数太少了,但是考虑到他们庞大的数量(几十万的规模)可以预想他们跟官方镜像一样流传甚广。
我们又分析了影响普通镜像中的高危漏洞,图4展示了关键的结果:
[图四:普通镜像中含有高危漏洞的软件包]
有趣的是,不同于官方镜像中首要祸源在于mercurial,在这些普通的镜像中,openssl,bash,和apt成了祸源的榜首。我们怀疑官方的和普通这种数字上的差异来源于发行版的差异,他们占据了这些镜像的大部分。官方镜像通常基于Debian并且其中一一大部分包含mercurial包。而普通的镜像,却通常基于Ubuntu因而有bash,apt,和/或openssl相关的漏洞。
教训
容器技术带来软件开发中的变革,它提供了一个十分高效的路子可以将开发者开发的软件在数分钟或者几小时内搬上生产环境运行,而传统的方式可能需要几天甚至数月。但是我们的数据显示这种优势有其弊端,没有良好的运维和安全管理的措施,我们冒着让我们的软件生态环境更加的易于收到安全攻击的危险。
容器为运行于不同容器之间的运行程序提供了一层安全隔离,因为提高了安全性。容器当然还是需要和其他的容器和系统进行通讯,因为它们还是会其基于的镜像中包含的漏洞而收到远程的攻击,包含一些在我们的分析中没有覆盖的。再者,在多种多样的环境中启动大量的容器的轻便与快速,在你的共有云上,私有云上,笔记本上,让追踪和防护有安全漏洞的容器变得更加困难。部署容器的高效性,大大的加速了部署软件的多样性,结果让环境中的新的漏洞越来越多。
使用容器的另外一个根本点在于,包管理已经被转移到了容器的内部,而传统的方式是仅仅是基于安装在虚拟或者实体操作系统层面上。这种改变主要根源于虚拟机和容器提供了不同层面的抽象。虚拟机提供的是以主机为中心的抽象,其特点是长期不停机,包含了不同应用所需的的软件包。与之相对的,容器提供的是一个更加以进程为主的抽象,其特点是短暂性,可以到处运行,定型后不改变,仅仅包含运行一个应用所必须的软件包。任何更新都需要重新构建容器,从而保持容器的不可修改性,这样让任何的漏洞同时被复制。
另外,向DevOps模式的转变,开发者开始为他们开发的应用的软件包负责意味着现在开发者开始负起了维护软件包的责任。除了操作系统的软件包,开发者在容器中可以包含应用层面中的模块如pip(python),npm(node),和maven(java),而这些都在我们的研究之外,然而它们也可能带来新的安全漏洞。因为开发者更加关注快速的将新的功能给尽早的弄出来,这让保持老的镜像更新变得更加困难,正如我们的研究呈现的一样(如官方的与201年4月发布的Centos 5.11镜像仍然包含shellshock漏洞,该漏洞是八个月前,2014年9月被爆出的)。
一个很好的避免这些问题的方式是经常用最新的更新重新构建镜像。重新构建的过程必须啊使用发布商发布的最新的基础镜像,并且不能使用任何缓存的镜像层(如:使用在apt-get upgrade的时候加上 -no-cahce
)。但是在一旦发现漏洞从头重新构建,并且重新部署所有的容器的开销太大,太不实际了 - 漏洞出的频率太高,每天都会爆出好几次,并且很难评估每一个安全漏洞的的影响范围。加之,更新容器的软件包很可能给容器中的应用带来负面影响和不稳定性,而这即时用复杂的测试也未必能捕捉到,这让人更加不情愿经常更新。
结论
我们的发现鼓励使用严格的运维管理流程,实时的分析镜像中的内容,清楚其中的内容和包含的漏洞。镜像应该经过安全漏洞的扫描,并且根据漏洞的严重程度来标记是否需要更新。任何重大的漏洞都应该被及时的发现,并且应该可以触发对这些有隐患的镜像进行隔离。镜像不仅仅应只从操作系统层面进行扫描,也应从应用的层面的安全漏洞进行扫描。这些流程应该被集成到持续构建的框架中,这样在享受容器带来的全面福利的同时,仍然保持着好的安全习惯。