一、别让你的容器踩了基础镜像投毒的坑
很多开发者用容器的时候,只会盯着自己写的应用代码,却忽略了最底层的基础镜像——这就像你盖房子,只看自己装修的客厅,却没检查地基用的砖头是不是被人掺了水泥。去年我接触过一个电商公司的运维事故:他们上线的支付容器里,每天自动往境外发数据库密码,追查下来才发现,他们用的公开openjdk基础镜像里被植入了后门脚本。这个就是典型的供应链攻击,从基础镜像投毒开始,绕开了应用层的防护,直接偷到了核心数据。
1.1 基础镜像投毒的大白话解释
你去Docker Hub拉一个node镜像,别人如果提前在这个镜像里加一段代码,比如每次请求都偷偷把环境变量里的密钥传到黑客服务器,你完全看不到。这个被改了的镜像就是“带毒镜像”,只要你拉来用,就等于把后门放进了自己的线上环境。
1.2 真实踩坑的常见场景
创业公司的技术团队因为赶进度,直接用了网上找的“最新基础镜像”,没检查是不是被篡改过;或者用了没扫描的自建镜像仓库,把带毒镜像推上去,结果整个公司的服务都被挖矿脚本占满CPU,花了3天才排查完。
二、阿里云ACR的默认配置,你可能悄悄踩了雷
很多人用阿里云容器镜像服务ACR,却没改默认设置,这就像你给家门装了锁,但忘了锁钥匙是随便挂在门上的。ACR默认的镜像自动扫描是关闭的,签名校验也是可选的——也就是说,不管你推上去的镜像有没有漏洞,有没有被篡改,ACR都不会拦着;你的K8s集群拉镜像的时候,也不会检查这个镜像是不是被合法签名过。
2.1 配置缺失的具体风险
我之前帮一个小团队做安全排查,他们的ACR实例里有超过200个镜像,全都没开自动扫描。其中有一个node:14的镜像,被检出12个Critical级别的漏洞,包括远程代码执行,而他们已经用这个镜像部署了5个线上服务。
2.2 为什么大家容易忽略这些配置
不是大家不想弄,是这些配置藏得有点深:ACR的自动扫描开关在“实例管理”的“安全设置”里,签名校验要在“镜像版本”里手动给每个镜像加,很多新人第一次用ACR,根本不会注意到这些选项。
三、端到端防线怎么搭?从ACR到K8s的全流程配置
这个防线的核心是两个动作:让ACR帮你把好镜像的入口,让K8s帮你把好镜像的出口。只要这两步做好,90%的供应链攻击都能挡住。
3.1 第一步:开启ACR的自动镜像漏洞扫描
ACR自带的自动扫描功能,只要你开了,每次往ACR推新镜像,它会自动扫一遍,有严重漏洞直接给你发邮件或者短信通知。操作也不难,用阿里云CLI就能搞定,不用去控制台点来点去,适合批量配置:
# 先登录阿里云CLI,替换成你自己的AK(Access Key ID)和SK(Access Key Secret),地域选你用的ACR地域
aliyun configure set --access-key-id your_ak_id --access-key-secret your_ak_secret --region cn-hangzhou
# 开启指定ACR实例的自动镜像扫描,替换成你的实例ID(在ACR控制台的实例详情里找)和命名空间
aliyun cr ScanImage --InstanceId cri-xxxxxx --NamespaceName your-team-namespace --AutoScanEnabled "true"
这个命令跑完之后,以后推上去的新镜像,ACR会每隔12小时自动扫一次,有Critical级别的漏洞会标红,不让你用。比如之前那个有12个漏洞的node镜像,开了扫描之后根本推不进生产环境,直接把风险挡在外面。
3.2 第二步:给镜像加签名校验,确保拉的镜像是“正规军”
就算ACR扫出来没漏洞,也可能是被篡改过的——黑客可以把带毒镜像扫出的漏洞全修好,再用自己的名字推上去。这时候就要用签名校验:只有用你自己生成的GPG密钥签名过的镜像,K8s才会拉。
# 先给你要信任的镜像签名,比如这个官方的node:14镜像,替换成你的ACR实例ID和镜像路径
aliyun cr SignImage --InstanceId cri-xxxxxx --RepoName your-team-namespace/node:14 --SignType "GPG" --SignKeyName your-gpg-key
签名之后,还要在K8s的部署配置里加上规则,只拉签名过的镜像:
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app-deploy
spec:
replicas: 3
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
containers:
- name: secure-app-container
# 镜像用你自己ACR里的镜像,带标签
image: registry.cn-hangzhou.aliyuncs.com/your-team-namespace/your-app:v1.0
# 强制只拉签名过的镜像,这个配置需要K8s集群开启ImagePolicyWebhook准入控制器,后续可以根据团队规模配置
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: acr-pull-secret
这里要注意,ImagePolicyWebhook的配置只要在K8s里开了,就会自动拒绝拉未签名的镜像,比如黑客投毒的镜像就算名字跟你一样,没签名也拉不起来。
3.3 第三步:基础镜像的“出身认证”
别用公开镜像直接改了就推,要用ACR官方提供的基础镜像。阿里云ACR里有官方的openjdk、node、nginx这些基础镜像,都是阿里云自己扫描过的,没有被投毒的风险。你可以把这些官方镜像做成自己的基础镜像,改了代码之后再推上去,再签名。比如我现在给团队做的规范里,基础镜像只能用ACR官方的,不准用Docker Hub的,从根源上减少风险。
四、这个方案的优缺点和注意事项
4.1 优点
配置好之后,整个流程自动化,不用人工盯:ACR自动扫漏洞,K8s自动拒拉未签名的镜像,不用天天查镜像的安全状态。适合中小团队,不用额外花钱买安全工具,只用ACR的基础功能就能搞定。
4.2 缺点
初期配置有点麻烦:要开CLI的权限,要生成GPG密钥,还要配置K8s的准入控制器。还有如果团队里有人忘了签名就推镜像,服务会起不来,所以要在CI/CD流水线里加自动签名的步骤,比如Jenkins里推镜像的时候自动调用签名命令,没人能绕过去。
4.3 注意事项
GPG密钥一定要备份,丢了之后之前所有签过名的镜像都失效,所有服务都会起不来;扫描出来的Critical漏洞必须24小时内修复,别拖;生产环境严格要求签名校验,测试环境可以松一点,比如允许拉未签名的镜像,方便调试。
五、总结
容器安全不是靠一个工具就能搞定的,ACR的镜像漏洞扫描和签名校验,是整个安全防线的入口。很多开发者忽略了这两个配置,结果被供应链攻击钻了空子。只要你按上面的步骤把ACR的扫描开了,给常用的镜像签了名,K8s配置好拉镜像的规则,就能挡住90%以上的基础镜像投毒风险。现在把这两个配置当成容器部署的标配,你的服务就能更稳,不会因为底层的坑掉链子。
评论
围绕“阿里云容器镜像服务ACR镜像漏洞扫描与签名校验配置缺失,供应链攻击从基础镜像投毒开始,端到端防线构筑实践”参与讨论