2. 镜像安全基础:容器镜像的组成与生命周期、常见镜像安全威胁与安全原则
2.1 容器镜像的组成与生命周期
容器镜像是云原生应用交付的核心单元,理解其组成与生命周期是实施镜像安全策略的前提。
2.1.1 镜像的物理组成
一个容器镜像由多层只读文件系统叠加而成,每一层对应 Dockerfile 中的一条指令。镜像的元数据(如 CMD、ENTRYPOINT、环境变量)存储在 JSON 格式的 Manifest 中,并通过摘要(Digest)进行唯一标识。
| 组件 | 说明 | 安全关注点 |
|---|---|---|
| 基础层 | 源自基础镜像(如 alpine:3.18, ubuntu:22.04) | 基础镜像本身可能包含已知漏洞 |
| 依赖层 | 通过 RUN apt-get / pip install / npm install 添加 | 第三方库漏洞、恶意包投毒 |
| 应用层 | COPY/ADD 应用代码与配置文件 | 硬编码密钥、敏感配置泄露 |
| 运行时层 | ENTRYPOINT/CMD 定义启动行为 | 以 root 运行、提权风险 |
| Manifest | 镜像的元数据清单(JSON) | 篡改或签名缺失 |
2.1.2 镜像生命周期阶段
镜像安全必须覆盖从构建到运行的全生命周期,每个阶段都有对应的安全控制点。
镜像生命周期安全控制点: 构建(Build)→ 存储(Registry)→ 分发(Pull)→ 部署(Run)→ 运行时(Runtime)→ 废弃(Retire)
2.2 常见镜像安全威胁
镜像安全威胁贯穿整个生命周期,主要分为以下三大类:
2.2.1 漏洞(Vulnerabilities)
操作系统包(apt/yum/apk)和语言依赖库(pip/npm/maven)中的已知 CVE 是镜像中最普遍的安全问题。攻击者利用这些漏洞可实现远程代码执行、权限提升或数据泄露。
关键数据: 根据 2024 年云原生安全报告,超过 70% 的生产容器镜像包含至少一个高危或严重漏洞。基础镜像版本越旧,漏洞密度越高。
2.2.2 恶意软件(Malware)
攻击者通过以下方式将恶意代码植入镜像:
- 基础镜像投毒: 在公共仓库上传包含后门的基础镜像(如伪装成流行库的 typo-squatting 攻击)。
- 依赖包劫持: 通过恶意 npm/pip 包在构建阶段执行挖矿、反弹 shell 等行为。
- 构建时注入: 利用 CI/CD 流水线漏洞在构建过程中注入恶意层。
2.2.3 配置泄露(Configuration Leakage)
镜像层是持久化的,即使后续层删除了文件,前一层仍保留副本。常见泄露类型:
| 泄露类型 | 示例 | 风险等级 |
|---|---|---|
| 硬编码密钥 | 、数据库密码、JWT Secret | 严重 |
| 证书/私钥 | .pem, .key, .crt 文件 | 严重 |
| 配置文件 | .env, config.json, application.yml | 高 |
| 历史命令 | .bash_history, .npmrc 中的 | 中 |
⚠️ 常见误区: 在 Dockerfile 中通过 RUN 命令设置环境变量(如 ENV PASSWORD=xxx),然后后续层删除该变量,但变量值仍存在于镜像历史层中。使用 docker history 命令即可查看。
2.3 镜像安全原则
基于上述威胁模型,业界总结出以下核心安全原则:
2.3.1 最小化原则(Minimalism)
- 使用最小基础镜像(如
alpine、distroless、scratch)减少攻击面。 - 仅安装运行时必需的依赖,移除构建工具、调试工具和 shell。
- 多阶段构建(Multi-stage Build)分离构建环境与运行环境。
2.3.2 不可变原则(Immutability)
- 镜像构建后不应修改,每次变更应生成新镜像并更新摘要。
- 使用内容寻址存储(Content-Addressable Storage),通过 Digest 而非 Tag 引用镜像。
- 启用镜像签名(如 Cosign、Notation)确保镜像来源可信。
2.3.3 扫描与修复原则(Scan & Remediate)
- 在构建阶段和存储阶段均执行自动化漏洞扫描。
- 建立漏洞修复 SLA:Critical 漏洞 24 小时内修复,High 漏洞 7 天内修复。
- 使用基础镜像自动更新流水线(如 Renovate、Dependabot)保持基础镜像最新。
2.3.4 运行时防御原则(Runtime Defense)
- 禁止容器以 root 用户运行,使用
USER指令指定非特权用户。 - 设置文件系统为只读(
readOnlyRootFilesystem: true)。 - 限制 Linux Capabilities,移除
SETUID、SETGID、SYS_ADMIN等危险能力。
2.3.5 供应链验证原则(Supply Chain Verification)
- 使用软件物料清单(SBOM)记录镜像中所有组件及其版本。
- 验证基础镜像和依赖包的签名与完整性。
- 建立可信镜像仓库白名单,禁止从不可信源拉取镜像。
2.4 镜像安全实践清单
以下清单可作为团队实施镜像安全基线的最低要求:
| 阶段 | 检查项 | 工具/方法 |
|---|---|---|
| 构建 | 使用官方签名基础镜像 | Docker Hub 官方镜像、Google Distroless |
| 构建 | 多阶段构建分离构建产物 | Dockerfile 多阶段语法 |
| 构建 | 扫描 Dockerfile 中的敏感信息 | Trivy、Snyk、Checkov |
| 存储 | 镜像签名并验证 | Cosign、Notation |
| 存储 | 定期扫描仓库中所有镜像 | Trivy、Grype、Anchore |
| 分发 | 通过 Digest 而非 Tag 拉取镜像 | image@sha256:xxx |
| 部署 | 准入控制策略验证镜像签名与漏洞等级 | Kyverno、OPA/Gatekeeper |
| 运行时 | 非 root 运行、只读根文件系统 | Pod Security Standards |
核心结论: 镜像安全不是单一工具或策略能解决的问题,需要从构建到运行时的全生命周期视角,结合最小化、不可变、扫描修复、运行时防御和供应链验证五大原则,构建纵深防御体系。本章后续将深入讲解如何通过准入控制将这些原则落地为可执行的策略。