摘要

腾讯云容器服务TKE目前拥有国内超大规模的Kubernetes集群,运行了包括游戏、支付、直播、金融等多个应用场景,集群的稳定运行离不开安全能力的保驾护。腾讯云容器安全服务站在业内最前沿的云原生安全视角,持续为TKE的安全治理提供指导并沉淀了丰富的思考和最佳实践。

本文将结合我们在容器基础镜像方面的安全建设和运营实践,分享我们对于基础镜像的安全治理和安全运营的思考。

1.背景

云原生安全架构的设计中,一个重要的思想就是安全左移,即在软件生命周期的更早阶段,投入更多的资源和安全能力,来更有效的收敛安全问题。容器镜像作为承载云原生应用的重要载体,作为云原生应用生命周期的源头,其安全性对云原生系统的安全有着重要的意义。确保容器镜像的安全性,是实现安全左移最重要的手段之一。

腾讯云千万核规模的容器集群,有着百万量级规模的容器镜像。如何针对这些镜像进行风险管控、如何快速的发现安全风险、如何高效的收敛安全风险,尤其是在重大漏洞爆发等应急场景下,如何快速的进行风险识别、定位和修复。这些问题给容器镜像的安全运营带来重大的挑战。

在镜像的安全治理和运营上,我们遵循着从镜像的构建、传输、存储、运行等全生命周期各个环节进行安全管控的思路,在镜像安全的维度,实现DevSecOps的闭环。

本文将重点介绍我们在容器基础镜像的安全治理和运营上的一些思路和实践,后续将针对镜像安全治理的其它环节,持续分享我们的一些经验。

2.什么是基础镜像

在介绍基础镜像前,我们先回顾下容器镜像的概念。镜像是由按层封装的文件系统和描述镜像的元数据构成的文件系统包,包含应用所需要的系统、环境、配置和应用本身等。

分层存储是容器镜像的主要特点之一,从图1可以看出,每个镜像都是由一系列的“镜像层”组成。当需要修改镜像内的某个文件时,只会对最上方的读写层进行改动,不会覆盖下层已有文件系统的内容。

图1 容器镜像的层级关系

当提交这个修改,生成新的镜像时,保存的内容仅为最上层可读写文件系统中被更新过的文件,这样就实现了在不同的容器镜像间共享镜像层的效果。图1是一个简单的容器镜像示例,最上层是容器的读写层,剩余的是只读层。

回到基础镜像上,不同容器镜像间共享的镜像层,就组成了所谓的基础镜像。在图1的示例中,FROM的ubuntu镜像,就可以认为是这个镜像的基础镜像。基础镜像其实是一个相对的概念,通俗一点说就是:其它的镜像我拿来用了,那么他这些个层组成的镜像对我来说就是基础镜像。

图2 镜像间的依赖关系

例如图2,有A、B、C三个镜像,B是在A的基础之上构建的,C又是在B的基础之上构建的,那么A就是B的基础镜像,A和B都是C的基础镜像(只不过C不会显示的看到A)。这样看来,上游的业务镜像,很有可能是下游业务镜像的基础镜像。

3.为什么基础镜像的安全性很重要

3.1 基础镜像来源渠道广

我们知道,在镜像的构建和使用流程中,最原始的基础镜像通常包含以下一些类别:

首先就是操作系统类的基础镜像,包括常见的busybox镜像、alpine镜像、centOS镜像、ubuntu镜像等;其次就是编程语言类的镜像,比如java镜像、python镜像、nodeJs镜像等;再就是应用类的基础镜像,比如nginx镜像、tomcat镜像、jetty镜像等。

对于这些镜像,常用的获取渠道都是通过Docker Hub等公开仓库,直接下载使用。根据《腾讯云容器安全白皮书》[1]、《容器安全在野攻击调查》[2]的数据显示,近

一年内发现的供应链恶意镜像中(图3 横坐标为镜像上线时间,纵坐标为下载数量),python、logstash、java类的基础软件镜像下载数量最大,通常4-5个月就可以达到10w左右,通过假冒常用基础软件镜像是攻击云原生软件供应链的重要环节之一。

图3 镜像供应链影响分布

假冒的恶意基础镜像种类大致分三种:1、编程语言开发环境;2、基础应用环境(wordpress、mondb 等);3、机器学习相关套件。其中,编程语言类镜像数量比例最大,占比达到47%。

图4 供应链恶意镜像种类比例

从上面的数据可以看出,这些传播量如此巨大的恶意镜像,实际上就是以基础镜像的理念来进行传播,攻击者通过构建一个适用于大众需求的基础镜像,通过吸引用户去下载,从而达到了快速大规模扩散安全风险的目的。

3.2 基础镜像覆盖范围广

根据前文对基础镜像以及镜像之间依赖关系的描述,基于某个基础镜像所衍生出来的镜像,将组成一个树状结构。从镜像仓库的角度看,所有的镜像根据依赖关系,将会组成一个森林的结构。

图5 仓库镜像的依赖关系

当我们的业务相对简单,并且规模较小时,这个依赖关系可能就是个简单的深度为2的树。规模达到一定量级之后,就会变成一个复杂的森林,每一棵树的度将会非常大,深度很有可能达到4、5甚至更大。

我们选择了47w个镜像作为样本,对仓库中部分镜像进行了初步的统计分析,发现这47w个镜像依赖了26299个基础镜像,其中:

  • 50%左右的镜像(24w)依赖了13个基础镜像,其中12个包含中危(及以上)漏洞;

  • 90%左右的镜像(43w)依赖了637个基础镜像,其中571个包含中危(及以上)漏洞;

  • 26299个基础镜像中,只有4.6%不含中危及以上的漏洞,其余95.4%均带有中危及以上的漏洞。

从上述数据可以看出,这些基础镜像覆盖范围非常广,一旦出现安全问题,其影响的镜像数量也将非常巨大。

4.基础镜像的安全治理

保证基础镜像的安全性,是容器镜像安全治理中最基础、也是最重要的一个环节。我们在基础镜像的安全治理上主要分为两大方面:一方面就是“控增量”,另一方面就是“收存量”,这个治理思路,跟总体的容器镜像安全治理思路是一致的。

接下来将针对这两个方面分别做介绍。

4.1 控增量

控增量主要是指对于新增加的容器镜像,需要在基础镜像的维度,实现全面的安全管控。实现路径主要包括规范镜像的构建流程要求、维护黄金镜像等。

4.1.1 规范镜像构建流程

明确基础镜像的构建要求。针对最原始的基础镜像(包括引用上游的业务镜像作为基础镜像构建下游业务镜像),制定明确的构建要求,例如可以包括:

  • 仅安装必要的软件,减小镜像体积,避免不必要的可执行程序、库引入安全问题;

  • 默认禁用root用户启动镜像、配置最小权限用户,实现基础镜像的权限收敛;

  • 基础镜像需进行安全性评估,保证已知安全漏洞被修复、无敏感信息存在、未引用高危组件、有安全基线配置等;

  • 坚决不允许直接使用Docker Hub等公开仓库的镜像作为基础镜像发布

  • 在构建基础镜像时,应考虑企业内的业务场景,尽量构建多个适用于不同业务场景的基础镜像等。

明确终端业务镜像的构建要求。针对叶子节点的终端业务镜像,明确其对基础镜像的使用要求,例如可以包括:

  • 只能使用特定版本的基础镜像,不可以使用latest以及其它来源的镜像作为基础镜像;

  • 根据业务的特点,选择最合适的基础镜像,避免引入更多的攻击面等。

4.1.2 维护黄金基础镜像仓库

黄金镜像是指已经过安全评估,解决了已知的安全风险,可以直接使用的镜像。对于常用的基础镜像,可以维护一个黄金基础镜像仓库,要求所有业务镜像在构建时,都只能以黄金镜像仓库中的镜像作为基础镜像。

在构建黄金镜像仓库时,一定要有一套完整的闭环流程,确保黄金镜像仓库中所有镜像的安全性。例如:全面的风险发现流程、高效的风险修复流程、完整的风险确认流程等。

4.2 收存量

收存量主要是指,对于已存在的容器镜像,可以从基础镜像的维度,实现安全风险的收敛。实现路径主要包括细粒度的风险检测、制定镜像的更新要求以及清晰的权责划分等。

如本文开头的介绍,仓库中的镜像几乎成树状结构分布,而且随着业务复杂性以及分工粒度的增大,这个树状结构将会变得越来越深,也会越来越复杂。

在镜像仓库中,一旦基础镜像存在安全风险,影响面将会大幅扩散,通过常规的安全收敛方法去修复镜像中的安全风险,存在工作量大,依赖项多、业务无法修复等诸多问题,且在后续的镜像迭代过程中,风险也会再次出现。

图6 基础镜像风险扩散示例

因此对于存量镜像的安全风险收敛,首要解决的问题就是基础镜像的安全风险收敛问题。

4.2.1 细粒度的风险检测能力

基础镜像识别。在对存量镜像从基础镜像的维度进行风险收敛前,首先需要充分利用镜像的层级特性,通过对仓库中的镜像进行扫描分析,根据镜像层的引入层关系以及依赖关系,识别哪些镜像是基础镜像。

风险检测与定位。对于容器镜像的风险检测,我们使用腾讯云容器安全服务(TCSS)的镜像安全检测能力,除了对镜像中的漏洞、恶意程序、敏感文件等风险点进行精准的检测外,还会更细粒度的将相关风险点对应识别到确定的镜像层上。

这样通过对镜像层的信息收集,在扫描到安全风险之后,根据安全风险类型的信息,识别在镜像中所属的镜像层,是在哪一阶段被引入到镜像中的,通过此方法来判断安全风险的来源于哪一层。

4.2.2 规范镜像更新流程

明确基础镜像更新要求。针对基础镜像(包括引用上游的业务镜像作为基础镜像构建下游业务镜像)的更新,制定明确的更新流程,例如可以包括:

  • 对于基础镜像的常规版本升级,需要满足前文中描述的构建要求,做好清晰的版本变更描述;

  • 对于检测到的安全风险,基础镜像需要在第一时间实现安全加固,消除安全风险,在满足构建要求的前提下,生成新版本的基础镜像。

明确业务镜像的更新要求。针对业务镜像,制定明确的更新流程,例如可以包括:

  • 对于常规功能性的版本升级,可以参考对新增镜像的要求来操作;

  • 对于检测到的安全风险,如果安全风险完全存在于基础镜像中,业务镜像可以等其依赖的基础镜像完成修复后,在新版本基础镜像之上重新构建自己的业务镜像(版本可以不变);如果安全风险存在于业务本身的层级中,则需要在原来基础镜像的基础上,修复相关问题,构建新版本的业务镜像。

需要注意的是,不管是哪种方式的镜像更新,在完成更新操作后,都需要使用镜像检测能力,对镜像重新进行风险评估。

4.2.3 清晰的权责划分

企业内部基础镜像的生成和应用过程中,应遵循谁生成谁维护的基本原则,镜像的安全性由镜像的生成者负责。在企业内部,基础镜像的生成和应用过程,往往会由多个团队多个角色方参与,例如由基础运维团队提供企业内统一的底层操作系统基础镜像,再由内部负责容器PaaS平台服务的基础平台团队基于操作系统基础镜像,再封装容器PaaS平台基础镜像,业务运维团队为了支撑自身业务上容器平台,会基于业务属性研发需求在容器PaaS平台基础镜像基础上,再封装出本业务需要的业务标准基础镜像,供业务的研发同学使用。

业务的研发同学默认会遵守本业务团队的研发规范要求,基于业务标准基础镜像再合入业务代码构建最后的业务容器镜像,最终业务容器镜像会在容器PaaS平台上部署使用。在这种逐层封装应用的过程中,每层镜像的生产方为其安全性负责,需在发布之前进行安全扫描和已知安全风险修复。

安全团队协同各角色方制定内部镜像构建、存储、发布的安全规范要求,并提供相应的安全扫描工具能力,并将安全工具集成至公司的DevOps平台中,实现自动化检测,并设定安全控制策略。

除了镜像的生产方主动在DevOps流程中进行安全检测和风险修复外,安全团队也可对内部镜像仓库进行监控和安全巡检,要求镜像仓库服务提供镜像资产查询接口,能准确定位到镜像资产所有人,针对安全巡检中发现的风险推送镜像资产所有人进行修复。安全侧对仓库巡检发现的高风险镜像,可以对风险引入的镜像层级进行定位,如果安全风险完全存在于基础镜像中,业务镜像可以等其依赖的基础镜像完成修复后,在新版本基础镜像之上重新构建自己的业务镜像(版本可以不变);如果安全风险存在于业务本身的层级中,则需要在原来基础镜像的基础上,修复相关问题,构建新版本的业务镜像。

5.总结

本文从基础镜像安全风险治理的角度,介绍了我们在基础镜像安全运营上的一些思路和方法。基础镜像的安全治理是容器镜像安全治理最重要的环节之一,基础镜像的安全风险收敛对于镜像的安全风险收敛有着重大的意义。

后续我们将持续分享我们在容器安全上的运营实践和经验,希望感兴趣的读者可以一起沟通交流。

6.参考文献

  • https://mp.weixin.qq.com/s/k8YYgxO4nXYhgY_lr7zgBg

  • https://mp.weixin.qq.com/s/oynjO8Q3IgZJt21HwxxMgA

关于腾讯容器安全服务(TCSS)

腾讯容器安全服务(Tencent Container SecurityService, TCSS)提供容器资产管理、镜像安全、集群安全、运行时入侵检测等安全服务,保障容器从镜像构建、部署到运行时的全生命周期安全,帮助企业构建容器安全防护体系。

腾讯从2018年9月30日启动全面云原生上云战略,至今已经有数千万核心规模。容器安全服务产品团队结合业内最大规模容器集群安全治理运营经验打磨产品,推动行业标准及规范的编写制定,并首发《腾讯云容器安全白皮书》,对国内容器环境安全现状进行分析总结,助力云原生安全生态的标准化和健康发展。

声明:本文来自安全内参,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。