6.3 容器

云原生生态系统延续了物理服务器和虚拟机 (VM) 等传统计算模型,广泛使用容器。因此,当涉及到容器及其相关的编排系统(如 Kubernetes)时,我们必须讨论容器和相关的软件供应链问题。

随着计算抽象的成熟,我们已经看到了从虚拟机 (VM) 到容器的转变。根据行业领导者 Docker 的定义,容器是“打包代码及其所有依赖项的标准软件单元,因此应用程序可以快速可靠地从一个计算环境运行到另一个计算环境。容器比 VM 更轻量级、更动态、更可移植,后者需要每个 VM 都有一个来宾操作系统(参见图 6.3)。

图6.3

容器的主要好处之一是它们允许开发人员将他们的软件代码、相关库和依赖项打包到一个轻量级的工件中。此项目是可移植的,能够在支持基于容器的部署的各种托管环境和基础结构中运行。

虽然这种捆绑对可移植性和效率等活动非常有益,但它也为不安全或易受攻击的依赖项打开了大门,这些依赖项可以包含在容器中,然后大规模复制。这种情况也经常发生,在公共容器映像存储库(如 DockerHub、Google Container Registry 等)中,任何人都可以使用容器映像来使用和重用。

事实上,帕洛阿尔托的 Unit 42 威胁研究小组 2021 年的一项研究发现,在对 1,500 多个公开可用的容器映像的研究中,96% 的映像中存在已知漏洞,并且 91% 的映像至少存在一个严重或高度漏洞,具体取决于 CVSS 等来源的严重性评分(www.paloaltonetworks.com/content/dam/pan/en_US/assets/ pdf/reports/Unit_42/unit-42-cloud-threat-report-2h-2021.pdf)。

这项研究还指出,图像的依赖关系越多,平均而言,它就越有可能具有更高的漏洞计数。因此,诸如减少攻击面或将依赖项和代码的数量最小化到仅容器和应用程序运行所需的依赖项和代码数等工作被广泛认为是安全最佳实践。

与其他形式的应用程序和软件交付非常相似,部署容器也保证了透明度。通过对容器使用 SBOM,您可以查看容器映像中的每个项目,这有助于识别软件供应链中的漏洞并在整个软件开发生命周期中进行修复。这包括从源、生成、暂存、部署和运行时阶段。漏洞可以在整个开发周期的任何阶段引入,因此在整个过程和阶段生成 SBOM 可以允许在整个生命周期中查看映像以及引入风险的任何更改。

尽管易受攻击的图像普遍存在,但创新工具正在出现,以帮助提供容器及其所需的软件组件和依赖项的透明度。Anchore 等领先供应商已经开发了允许组织生成 SBOM 的 OSS 工具。Anchore 的 SBOM 工具被称为 Syft,拥有一组强大的功能和语言支持。功能包括为容器映像、文件系统等生成 SBOM;支持开放容器计划 (OCI) 和 Docker 映像格式;以及使用 in-toto 框架支持已签名的 SBOM 证明的能力。(证明是我们将在本书的其他领域讨论的一个概念,例如第 11 章“消费者实用指南”。

Syft 支持领先的 SBOM 格式,如 CycloneDX 和 SPDX,如第 4 章“软件物料清单的兴起”中所述。另一个广受欢迎的 OSS 扫描仪是 Trivy,来自 Aqua Security 的团队。它支持以容器映像、文件系统、Git 存储库和 Kubernetes 资源为目标,以识别 CVE、OS 包和依赖项,以支持 SBOM 和声明性基础结构即代码中的错误配置。

容器领导者 Docker 甚至添加了原生 SBOM 功能。2022 年初,Docker 宣布能够简单地从 Docker Desktop 的 CLI 运行 docker sbom 并为任何 Docker 映像生成 SBOM (www.docker .com/blog/announcing-docker-sbom-a-step-towards-more-visibility-intodocker-images)。此功能是在开源社区和 Anchore 团队的协作下开发的,使用我们之前讨论过的 Syft 项目。Docker 团队解释说,这个附加功能旨在提高对供应链的信任,以查看映像中包含的内容,并使开发人员轻松完成该过程,以免妨碍生产力或速度。

从软件供应链的角度来看,容器及其相关生态系统存在广泛的潜在攻击媒介和需要考虑的风险。虽然很难列举每个攻击媒介,但我们肯定会在这里看到一些主要的攻击媒介,包括基础镜像、操作系统、Git 存储库、应用程序代码和依赖项以及 OSS 组件。由于云原生环境中涉及开发、安全和运营的团队数量众多,再加上保护容器的各种安全层,容器安全也变得更加复杂。这些涉及容器映像及其包含的软件、容器和主机操作系统之间的交互,以及在编排平台上运行的其他容器。此外,还存在与容器网络和存储以及容器在生产环境中部署到的运行时环境相关的攻击媒介和风险,该环境通常位于 Kubernetes 集群之上。

在讨论基础映像时,就像软件供应链中的任何上游组件一样,所有下游消费者和用户都可能受到供应链上游引入的风险的影响。基础映像是容器软件供应链中的关键步骤,因为在容器上运行的软件应用程序会继承构建应用程序的基础映像中包含的任何安全债务和漏洞。多个容器安全指南来源推荐的一个关键最佳做法是使用强化的基础映像。通常,这意味着基础映像已经过强化以减少漏洞,并且还被剥离为仅包含功能所需的基本要素。这通常称为攻击面减少,即删除不必要的组件,这些组件可以被利用来破坏容器及其上的应用程序。一些最受欢迎的基础映像包括 Alpine、Ubuntu 和 Debian。

在最小化容器攻击面的推动力中,出现了所谓的“无发行版”容器映像。无发行版容器映像仅包含应用程序及其运行时依赖项,从而删除了通常伴随常见 Linux 发行版的组件,例如包管理器、shell 或其他程序。NIST等来源在其“应用程序容器安全指南”(https://csrc.nist.gov/publications/detail/sp/800-190/final)以及行业领导者(如Liz Rice)的《容器安全》(O'Reilly Media,2020)一书中经常将最小化容器的攻击面作为最佳实践,该书讨论了减少攻击面以及其他容器安全建议。除了减少攻击面之外,无发行版图像还具有多种好处,例如最大限度地减少由于虚假 CVE 引起的扫描程序噪音、减少出处负担以及在大小方面更有效率,正如 Google 的容器工具无发行版 GitHub 页面 (https://github.com/ GoogleContainerTools/distroless) 中所引用的那样。

软件供应链安全初创公司 Chainguard 推出了 Wolfi,这是一套无发行版映像,在 CVE 方面比大多数传统容器映像 (www.chainguard.dev/unchained/introducingwolfi-the-first-linux-un-distro) 更安全。Chainguard 还开始引入对内存安全容器镜像的追求,这与 NSA 等来源关于将行业转向更安全的内存安全语言和生态系统的更广泛建议一致。

与其他 OSS 组件非常相似,组织通常从开放的 Internet 获取容器映像,当涉及到容器时,最受欢迎的来源之一是 Docker Hub (https://hub.docker.com)。顾名思义,Docker Hub 由 Docker 运行,用于查找容器映像并与团队和组织共享。为了正确看待 Docker Hub 及其托管的相关映像的受欢迎程度,在撰写本文时,该站点上有 20 张映像已被下载至少 10 亿次。也就是说,与任何其他软件组件一样,这些容器映像在映像文件中通常存在多个漏洞,组织可以通过在使用它们之前不进行尽职调查来继承这些漏洞和技术债务。如前所述,研究已经确定,Docker Hub 上公开提供的映像中,超过 90% 包含已知漏洞,其中极高比例的映像包含至少一个严重或高漏洞。再加上数十亿的下载量,您可以想象有多少易受攻击的容器在世界各地的企业环境中运行。

软件供应链供应商 Chainguard 等组织的进一步研究使用容器漏洞扫描工具 Trivy、Snyk 和 Grype 通过 Docker Hub (https://uploads-ssl.webflow.com/6228fdbc6c97145dad2a9c2b/624e233 7f70386ed568d7e7e_chainguard-all-about-that-base-image.pdf) 上的下载量来评估一些最流行的基础映像。Chainguard 发现,Node、Debian、Ubuntu 和 Red Hat UBI 等领先镜像都融入了大量的技术债务。这些图像的漏洞计数从 28 个到高达 800 个不等,具体取决于图像和使用的扫描程序。漏洞严重程度从低到严重不等,在所使用的三个漏洞扫描程序中,只有 Alpine: 3.15.0 映像不包含已知漏洞。正如该研究指出的那样,与其他产品相比,Alpine之所以得分如此之高,是因为它是一个面向安全的基础映像,包含不到10个软件包。这是一个减少攻击面和创建基础映像的示例,这些映像考虑了安全性,以降低组织风险。显然,容器化应用程序的每一层都可能增加风险状况,但建议从适当安全且最小的基础映像开始。

不仅基础映像是一个值得关注的话题,而且组织越来越多地采用建立强化容器的内部存储库的做法,这些容器已经过攻击面减少和强化,并由受信任的实体签名。这降低了团队从公共源拉取容器映像的可能性,因此他们可能会改用内部批准和存储的映像,以满足组织的安全性和合规性要求。最明显和被引用的例子之一是国防部 (DoD) 的 Iron Bank (https://p1.dso.mil/products/iron-bank),这是一个容器存储库,其中包含经过强化、批准和授权的容器映像,供美国空军 (USAF) 和更广泛的国防部使用。美国联邦民事机构也利用了这些强化映像,并紧随其后,建立了自己的内部安全容器映像存储库,以供使用和部署。

公共 Git 存储库代表了另一种可以在容器软件供应链中引入风险的途径。虽然与映像关联的 CVE 是衡量容器安全性的重要指标,但了解它们来源的存储库是另一个衡量标准,可告知组织对固有或潜在风险的理解。一个流行的项目,着眼于与公共GitHub项目及其存储库相关的配置和活动,是OpenSSF记分卡计划,我们将在第7章中讨论,标题为“现有和新兴的商业指南”。

应用程序代码、依赖项和 OSS 组件都存在风险,这些风险也可能导致容器镜像的漏洞配置文件。因此,在将容器引入运行时环境之前,使用应用程序安全最佳实践非常重要,例如对通过持续集成/持续交付 (CI/CD) 管道的容器实施静态应用程序安全测试 (SAST) 和软件组合分析 (SCA) 扫描。这些工具可以帮助识别容器内代码中的漏洞,这些漏洞可以在引入生产环境之前进行修正,恶意参与者可能会利用这些漏洞。

也就是说,尽管在生产之前将安全性向左转移并识别管道中或在构建期间的漏洞是很好的做法,但它们并不能减轻对运行时容器分析和监视的需求。管道中可能遗漏了漏洞,或者部署后可能出现了新的漏洞,因此除了管道可见性之外,组织还需要对容器运行时进行监视。正如云原生所提到的Computing Foundation (CNCF) 的云原生安全最佳实践白皮书 (https://cncf.io/blog/2022/05/18/announcing-the-refreshedcloud-native-security-whitepaper),云原生工作负载需要安全性 控件贯穿其整个生命周期,包括运行时。如果正确的工具和可见性已到位,安全团队可以了解运行时环境中的漏洞,更新容器映像并重新部署不再脆弱的映像。

需要指出的是,现代应用程序也绝大多数由开源代码和组件组成。安全领导者 Snyk 等组织发现 80% 的应用程序代码由 OSS (https://snyk.io/wp-content/uploads/Snyk-Docker-ContainerSecurity.pdf) 组成。当然,这种开源代码包含直接依赖关系和传递依赖关系,每个依赖关系都包含各自的漏洞。除了OSS代码和组件之外,容器镜像也是分层创建的,每一层的工具、库和附加组件都代表了引入风险的可能性。通过管理和控制添加到容器文件的其他代码和层,组织可以控制引入的风险。

使用容器时的另一个关键问题是主机基础结构本身。如前所述,这意味着 Kubernetes 集群作为业务流程协调程序运行,但也存在诸如底层 VM 之类的问题。这些问题包括 VM 的强化、其选择的操作系统以及与主机实例关联的网络控制。我们将在下一节中对此进行更多探讨。