今天,容器已经彻底改变了开发过程,并成为了DevOps模式的基石。但是容器带来的复杂安全风险并不总是显而易见,没有考虑到这些潜在威胁的组织非常容易受到恶意攻击。
本文将介绍容器是如何促进敏捷开发的,容器带来了哪些特殊的安全风险,以及组织可以做什么来保证容器化工作负荷的安全,从而超越DevOps达到理想的DevSecOps。
一、什么是容器
作为程序员,让我们回忆我们每天从事的熟悉得不能再熟悉的软件开发工作:在本地搭好开发环境,进行开发工作,接下来进行单元测试,把开发好的代码部署到测试系统,重复测试,最后部署到生产系统。
我们不可避免地会遇到这种情况:同样的代码,运行环境发生变化之后无法正常运行。比如代码从程序员的笔记本电脑切换到测试服务器,或者从一台物理服务器切换到公有云/私有云上。也可能是代码依赖的运行库版本发生变化,比如开发时用的python2.7, 但生产机上用的python3。又或是代码运行的操作系统发生了变化,比如开发及用的ubuntu,生产机用的redhat等等。
程序员除了投入时间在应用程序本身开发上之外,还需要花费额外的精力去处理这种环境或者说infrastructure问题,这种事情很让人头痛。作为一个应用程序开发人员,我对底层的这些环境问题不感兴趣,有没有一种办法能使的我不去考虑它们呢?有,使用容器技术。
简单地说,一个容器包含了完整的运行时环境:除了应用程序本身之外,这个应用所需的全部依赖、类库、其他二进制文件、配置文件等,都统一被打入了一个称为容器镜像的包中。通过将应用程序本身,和其依赖容器化,操作系统发行版本和其他基础环境造成的差异,都被抽象掉了。
二、为什么容器如此流行
在许多方面,容器是虚拟化的进阶版本。我们的目标是加快开发过程,创建一条从开发、测试到实现的更灵活的通道。无论如何,使用容器总是比成熟的虚拟机更轻量级。
搭建这条通路的核心问题在于应用程序的兼容性,因为应用程序需要某些版本的库——这可能恰好与其他应用程序的需求相冲突。容器完美的解决了这个问题,并且能够很好的与开发过程和管理基础结构结合起来。
容器通过虚拟化达到了更高的高度。虚拟化抽象硬件层,而容器抽象操作系统层,其实质上是充当了虚拟化操作系统的角色。容器化的工作原理就是将应用程序打包到包含所有必要库的容器中,以使应用程序正常工作,同时让它们彼此并不冲突。
在功能上,容器非常简单——容器只是一个文本文件,其中描述了应该在实例中包含哪些组件。容器的这种简洁性和轻量级的特性使得开发人员在整个生命周期中可以轻松的使用自动化(编制)工具进行相应的部署。
三、我们不顾一切为了胜利,但安全也很重要
容器具有显著提高开发效率的能力,即充当解锁DevOps的钥匙。这可能就是容器得到泛用的原因之一,据Gartner预估,到2023年70%的组织将运行容器化的工作负载。
在过去,开发、测试和部署应用程序的过程充满了荆棘,需要在开发人员和负责基础设施的团队之间不断来回奔波。现在,由于有了容器,开发人员可以在一个稳定的环境中构建和测试,并且只需要将完成的代码与定义该环境的规范一起发布即可。
在操作方面,团队只需要执行这个规范来创建一个可以随时使用的匹配环境就行了。现在,开发人员再也不用担心环境问题而引发的一系列冗长的调试。
容器 + DevOps意味着快速部署和开发,但这其中还缺少一个关键因素:安全。这就是为什么我们越来越多的听到关于DevSecOps的说法,因为开发者已经注意到仅仅使用DevOps模型不足以解决所有的安全问题。
四、容器所带来的一些安全风险
容器简化了开发过程,但在安全性方面引入了一些麻烦。当你将整个操作环境紧密的包装到一个容器中只是为了广泛的分发它时,这也增加了受攻击面,并打开了不同攻击向量的大门。这些与容器打包的库中,只要存在任何潜在的漏洞或缺陷,就会在后续散布到无数的工作负载中。
最危险的莫过于供应链攻击,即恶意攻击者不是通过扰乱应用程序,而是通过修改应用程序依赖的一个包或组件来发起攻击。因此,负责开发工作的团队需要评估他们正在开发的应用程序,以及是否每个库都通过容器配置作为一个依赖项被拉入。
容器安全的风险还包括启用容器的工具,例如Dockers或者k8s,这些工具同样需要被监视和维护。例如,你不应该允许系统管理员以root身份运行Docker容器。同样的,我们需要密切保护容器注册中心,以确保这些组件不会受到损害。
Docker(容器工具)
五、内核安全是容器安全的核心
我们在讨论容器安全时很容易忽略这样一个事实,即所有容器都依赖于同一个内核。容器中的应用程序彼此分离并不重要,重要的是每个容器都需要访问一个内核,毕竟,容器只是一种高级进程的分离罢了。
应用程序在容器中看到的内核与主机所依赖的内核是一样的。如果支持容器的主机上的内核容易被攻击,那么这个漏洞可能会被从容器内的应用程序启动的攻击所利用。
所以,内核由主机的所有容器共享这一事实意味着我们必须迅速修补有缺陷或漏洞的内核,否则所有容器都可能很快受到漏洞的影响。
因此,我们需要一些可靠的漏洞检测工具来帮助我们保护内核安全。例如泛联新安的CodeSense、BinSearch和iUnit,这些工具可以使我们更放心的使用容器。
六、维护问题
保持主机内核的实时更新是确保容器安全的一个重要步骤。需要修补的不仅仅是内核,还必须对容器拉入的库进行维护。但正如我们所了解的,持续的修补说起来容易做起来难。这可能就是为什么前不久一项研究显示:75%被分析的容器中都包含至少一个被分类为关键或高风险的漏洞。
例如,这些漏洞可能导致恶意攻击,攻击者依赖容器内的有缺陷的库来执行容器外的代码。通过破坏一个容器,攻击者最终可以达到他们预期的目标,这可能是主机系统或是另一个容器中的应用程序。
对于维护容器安全来说,这确实是一件令人头痛的事情。需要有人跟踪新的漏洞,已经有哪些漏洞已经被修复,哪些漏洞尚未修复。这个过程费时费力,而且需要专业技能。如果你的组织还没有掌握这些技能,得赶快开始了。
七、将安全无缝嵌入容器操作中
当涉及到信息安全时,使用尖端技术从而导致一些新的挑战是十分常见的现象。新的工具通常会优化原有流程和产生新的问题,对于容器来说也是如此。虽然这并不会减低容器在工作负载中的重要性,但提醒着我们需要更加密切的关注容器所带来的新的风险。
首先要做的就是培训开发人员和系统管理员了解容器安全性中的常见缺陷以及修复这些问题的最佳实践。和往常一样,采取正确的措施来减少安全漏洞将有助于保护你的企业,并且能让你的团队从尖端技术中受益,而不是遭受不眠之夜修补代码的痛苦折磨。