文章总结: 本文概述K8s核心架构,重点讲解红队场景下的横向移动技术。深入分析Kubelet未授权访问与APIServer未授权访问的漏洞成因及配置缺陷,演示利用kubeletctl和kubectl工具获取集群信息、窃取Token及执行命令的步骤,为容器环境渗透提供实战参考。 综合评分: 85 文章分类: 红队,渗透测试,云安全,漏洞分析,内网渗透
2026了,打red的时候遇到K8S还不知道咋横向吗(上)
原创
Syst1m
凌曦安全
2026年1月2日 16:35 上海
寒
K8S横向
正文开始前先提一下,凌曦安全团队课程的元旦优惠马上结束了,需要的小伙伴可以看一下这个链接介绍:Zer0 sec 正式更名为 凌曦安全!新的一年,新的课程,元旦特惠来啦~
一期课程课程大纲直达链接:https://www.yuque.com/syst1m-/blog/lc3k6elv0zqhdal3
MINOR COLD
本推文提供的信息、技术和方法仅用于教育目的。文中讨论的所有案例和技术均旨在帮助读者更好地理解相关安全问题,并采取适当的防护措施来保护自身系统免受攻击。
严禁将本文中的任何信息用于非法目的或对任何未经许可的系统进行测试。未经授权尝试访问计算机系统或数据是违法行为,可能会导致法律后果。
作者不对因阅读本文后采取的任何行动所造成的任何形式的损害负责,包括但不限于直接、间接、特殊、附带或后果性的损害。用户应自行承担使用这些信息的风险。我们鼓励所有读者遵守法律法规,负责任地使用技术知识,共同维护网络空间的安全与和谐。
本章为上篇,下篇讲解如何在Pod中干到物理节点、如何横向、如何接管K8S集群等,敬请期待
一、Kubernetes(K8s)简单介绍
简介
-
Kubernetes(简称K8s)是Google开源的分布式容器编排平台,核心目标是解决大规模容器集群的“部署、调度、运维”三大核心难题
-
当Docker容器数量从几个增长到数百、数千个时,手工管理会面临效率低下、资源浪费、故障恢复困难等问题,K8s通过自动化能力将容器集群的管理标准化、规模化
-
可以延续“集装箱”类比:
-
Docker:将应用打包成“集装箱”(容器),保证环境一致性和可移植性
-
K8s:打造“智能港口+物流调度系统”,负责“集装箱”的跨节点分配、动态扩容、故障替换、路径规划(网络访问)等全生命周期管理
核心架构
- K8s集群的“控制平面+节点”架构是实现分布式管理的基础,每个组件的职责与交互逻辑如下:
核心资源
-
K8s的资源对象是“声明式配置”的核心,每个资源对应特定的应用场景,关键资源的实操细节如下:
-
Pod:最小部署单元
-
本质:一组共享网络(同一IP)、存储(Volume)、PID命名空间的容器集合,容器间可通过localhost通信
-
实操关联:创建Pod需通过YAML文件定义(如nginx Pod的镜像、端口),执行
kubectl apply -f pod.yaml提交,Kubelet接收指令后调用容器运行时拉取镜像创建容器 -
生命周期:从“Pending(调度中)”到“Running(运行中)”,故障时会被Controller Manager重建
-
Deployment:无状态应用核心控制器
-
核心能力:声明副本数(replicas)、滚动更新、版本回滚(
kubectl rollout undo); -
示例:通过Deployment创建tomcat容器,可配置
securityContext: privileged: true开启特权模式(但存在安全风险),并通过Volume挂载宿主机目录。 -
Service:稳定网络入口
-
解决问题:Pod动态漂移(IP变化)导致访问不稳定
-
类型:
-
ClusterIP:集群内部访问(默认);
-
NodePort:暴露节点端口(如30080),外部可通过
节点IP:NodePort访问; -
LoadBalancer:对接云厂商负载均衡器(如阿里云SLB)
-
实操示例:通过YAML定义NodePort类型Service,可将Pod的8080端口映射到节点的30080端口,实现外部访问
-
ServiceAccount与Token
-
作用:Pod访问集群资源的身份凭证,Token存储在
/var/run/secrets/kubernetes.io/serviceaccount/token; -
权限关联:通过RBAC(基于角色的访问控制)绑定权限,如“hacker”ServiceAccount绑定
cluster-admin角色后,拥有集群最高权限(文档中高权限Token的核心来源) -
ConfigMap与Secret
-
ConfigMap:存储非敏感配置(如应用的数据库地址、端口),可通过环境变量或Volume挂载到Pod
-
Secret:存储敏感信息(如密码、证书),数据会base64编码(文档中提及的ServiceAccount Token就是Secret的一种)
-
Namespace:集群隔离工具
-
用途:按环境(开发/测试/生产)或团队划分资源,如
kube-system(系统组件)、default(默认命名空间) -
隔离范围:资源命名隔离(不同Namespace可存在同名Pod)、资源配额隔离(通过Resource Quota限制CPU/内存使用)
-
Ingress:七层路由
-
补充Service的不足:Service是四层(TCP/UDP)负载均衡,Ingress支持HTTP/HTTPS的域名路由(如
xxx.lazy.com指向不同Service)、路径路由(如/api指向后端服务)
核心工作流程(以创建一个Nginx Deployment并通过NodePort访问为例)
步骤1:用户提交部署请求(声明式API调用)
- 用户通过
kubectl apply -f nginx-deploy.yaml提交配置文件,YAML文件定义Deployment(管理Pod副本)和Service(NodePort暴露服务),YAML示例如下
-
kubectl工具将 YAML 配置转换为REST API请求(POST/PUT),发送至K8s API Server(默认地址:https://:6443)
-
请求内容包含:要创建的资源类型(Deployment/Service)、命名空间、规格(副本数、镜像、Service 类型等)
步骤2:API Server接收请求并执行“认证→授权→准入控制”三步校验
- API Server是集群唯一入口,所有请求必须通过三层校验,缺一不可
认证(Authentication)
-
验证请求发起者的身份,常见认证方式:
-
若为kubectl命令行操作:默认使用
~/.kube/config中的客户端证书(client-certificate)+私钥(client-key),或ServiceAccount Token -
若为程序调用:通过Bearer Token、OIDC 令牌等方式认证
-
认证失败:API Server直接返回
401 Unauthorized,请求终止 -
认证成功:进入下一步授权流程,同时记录请求者的身份(如
kubernetes-admin)
授权(Authorization)
-
基于RBAC(基于角色的访问控制)规则,检查认证通过的用户是否有“在 default 命名空间创建Deployment/Service”的权限:
-
核心校验逻辑:用户是否绑定了包含
apps/deployments/create、core/services/create权限的Role/ClusterRole -
例如:
cluster-admin角色包含所有资源的所有操作权限,普通用户需显式授权 -
授权失败:返回
403 Forbidden,请求终止 -
授权成功:进入下一步准入控制流程
准入控制(Admission Control)
-
对请求的资源配置进行“前置校验 / 修改”,分为两种类型:
-
验证型准入插件:校验配置合法性(如镜像是否在企业白名单、副本数是否超出命名空间配额、标签是否符合规范);
-
突变型准入插件:自动修改配置(如:注入默认的资源限制、添加Sidecar容器、为Pod自动挂载ServiceAccount Volume);
-
常见核心插件:
NamespaceLifecycle(校验命名空间是否存在)、ResourceQuota(校验资源配额)、ValidatingAdmissionWebhook(自定义校验规则) -
准入控制失败:返回
400 Bad Request,请求终止 -
准入控制成功:API Server将Deployment和Service的配置写入etcd(集群唯一数据存储),并返回
201 Created
步骤3:Controller Manager触发Pod创建逻辑
-
etcd中存储的Deployment配置会被
kube-controller-manager监听(内置Deployment控制器),执行以下操作: -
Deployment控制器检测到“期望的Pod副本数(此处示例为3个)”与“当前集群中匹配标签的Pod数(0个)”不一致
-
Deployment控制器自动创建
ReplicaSet资源(名称格式:nginx-deploy-<随机字符串>),ReplicaSet的核心作用是保证指定数量的Pod副本始终运行 -
ReplicaSet控制器监听etcd中的ReplicaSet配置,检测到副本数不满足后,向 API Server提交“创建3个Pod”的请求
-
API Server验证Pod配置后,将Pod对象写入etcd(此时Pod的
spec.nodeName为空,处于“未调度”状态)
步骤 4:Scheduler完成Pod调度(分配目标节点)
-
kube-scheduler(调度器)通过
Informer机制监听etcd中“未调度 Pod”(spec.nodeName为空),执行“预选 + 优选”两步调度:
预选(Filter):筛选符合条件的节点
-
排除不符合硬规则的节点,例如:
-
节点是否存活(Ready状态);
-
节点剩余CPU / 内存是否满足Pod的
resources.requests; -
节点是否有Pod亲和性 / 反亲和性冲突(如:Pod要求必须部署在
node-1); -
节点是否有污点(Taint)且 Pod 无对应的容忍(Toleration);
-
若所有节点都不符合,Pod会一直处于
Pending状态,调度器记录事件:FailedScheduling
优选(Score):对预选通过的节点打分
-
对符合条件的节点按“优选策略”打分(0-100分),例如:
-
LeastRequestedPriority:剩余资源越多的节点得分越高(优先调度到资源空闲的节点)
-
NodeAffinityPriority:匹配 Pod 节点亲和性规则的节点加分
-
BalancedResourceAllocation:CPU / 内存使用率越均衡的节点得分越高
-
选择得分最高的节点(若配置“反亲和性”,3 个Pod会被调度到不同节点)
确认调度结果
- 调度器将Pod的
spec.nodeName字段更新为目标节点名称(如:node-1、node-2、node-3),并写入etcd - API Server将调度结果同步给目标节点的
kubelet组件
步骤5:目标节点的Kubelet创建Pod和容器
-
每个节点的
kubelet会定期向API Server发起请求,监听“分配给当前节点的Pod”,接收到Pod调度指令后,执行以下操作: -
预处理阶段:
-
校验节点本地资源(CPU / 内存)是否满足Pod需求
-
挂载Pod所需的 Volume(如 ConfigMap、Secret、EmptyDir)
-
通过CNI(容器网络接口)插件(如 Calico/Flannel)为 Pod 创建网络命名空间,分配Pod IP(如
10.244.2.5),配置跨节点通信规则 -
容器创建阶段:
-
Kubelet通过CRI(容器运行时接口)调用containerd,执行镜像拉取:
containerd pull nginx:1.21 -
拉取完成后,containerd 创建容器运行时沙箱(Sandbox,通常是pause容器),Pod内所有容器共享沙箱的网络 / IPC命名空间
-
创建nginx容器,配置容器的端口、资源限制、环境变量等
-
状态上报阶段:
-
Kubelet启动容器后,将Pod状态更新为
Running,并通过API Server同步到etcd; -
Kubelet 持续监控容器状态(通过容器运行时的监控接口),若容器崩溃,按Pod的
restartPolicy(默认Always)重启容器
步骤6:Kube-proxy配置Service网络规则,实现服务暴露
-
kube-proxy运行在每个节点上,监听etcd中的Service配置(nginx-svc),根据 Service类型(NodePort)配置网络转发规则(默认iptables模式,也可配置ipvs模式):
-
为Service分配ClusterIP:API Server为nginx-svc分配集群内唯一的虚拟 IP(如
10.96.0.10); -
配置 iptables 规则:
-
在节点上创建
KUBE-SVC-<哈希值>链:将访问ClusterIP:80的流量转发到后端3个Pod的IP:80; -
创建
KUBE-NODEPORTS链:将访问节点IP:30080的流量转发到ClusterIP:80; -
配置负载均衡规则:iptables通过随机 / 轮询方式将流量分发到不同Pod
-
端点同步:
-
kube-proxy通过EndpointSlice(替代传统Endpoint)监听 Pod 的存活状态,若某个Pod故障(如:livenessProbe失败),自动将其从 iptables 转发规则中移除
步骤7:外部访问Nginx服务
-
客户端可通过任意节点的
IP:30080访问Nginx服务: -
例如:节点IP为
192.168.1.100,访问http://192.168.1.100:30080 -
流量路径:客户端→
节点 IP:30080→iptables规则转发→ClusterIP:80→后端Pod IP:80→nginx容器
二、Kubernetes Kubelet未授权访问
漏洞简介
- Kubelet未授权访问漏洞是因Kubelet组件认证/授权配置不当,导致未认证主体可访问其API端口(核心端口为:10250、10255),进而窃取集群信息、执行容器命令甚至控制节点的高危配置缺陷
- Kubelet在K8S节点上负责Pod / 容器生命周期管理、状态上报与指令执行,对外提供10250(HTTPS可写API,默认需认证)与10255(HTTP只读 API,默认关闭)两个核心端口
- 漏洞核心成因:由于
/var/lib/kubelet/config.yaml文件配置不当,开启了匿名访问(anonymous.enabled: true)且授权策略设为AlwaysAllow,而默认情况下kubelet监听的10250端口没有进行任何认证鉴权,就会导致未授权主体绕过认证/授权直接调用API
漏洞利用
- 访问kubelet的10250服务,发现存在未授权
-
使用kubeletctl工具进行漏洞利用
-
下载地址:https://github.com/cyberark/kubeletctl/releases/
-
列出kubelet的所有Pod
- 搜索容器里的Service Account
- 执行命令
三、K8s API Server未授权
漏洞简介
- API Server是整个K8S集群的核心入口,所有组件(如:kubelet、kube-controller-manager)和用户的操作请求(如:创建Pod、查询资源)都必须通过它处理
-
未授权访问的本质是认证环节失效或授权环节完全放行,导致攻击者无需提供合法身份凭证(如:token、证书),即可绕过权限检查操作集群资源:
-
认证(Authentication):验证请求者是谁,若
/etc/kubernetes/manifests/kube-apiserver.yaml中配置开启anonymous-auth=true,则允许匿名用户发送请求(无需任何凭证) -
授权(Authorization):验证请求者能做什么,若若
/etc/kubernetes/manifests/kube-apiserver.yaml中配置授权模式为AlwaysAllow(默认为Node,RBAC),则无论认证结果如何,所有请求都会被直接放行
-
API Server默认会开启两个端口(低版本):Insecure Port和Secure Port
-
Insecure Port
-
标识为
--insecure-port,值默认为0,表示此端口默认关闭,如果需要开启HTTP非安全端口模式,可以把--insecure-port的值设置为8080 -
默认IP是本地主机,标识为
--insecure-bind-address -
在HTTP中没有认证和授权检查
-
Secure Port
-
标识为
--secure-port,默认端口为6443 -
认证方式:令牌/客户端证书
-
在低版本的K8S中,如果
/etc/kubernetes/manifests/kube-apiserver.yaml有如下配置,则可能存在未授权访问漏洞 -
--anonymous-auth=true:允许任何没有提供身份凭证的请求以匿名用户身份发送到API Server,跳过身份验证的环节 -
--authorization-mode=AlwaysAllow:无论请求者是谁(包括匿名用户)、请求操作是什么,API Server都会直接放行,完全绕过授权检查环节 -
--insecure-port=8080:K8S API Server默认的6443安全端口(HTTPS协议)要求所有请求必须经过TLS加密,且强制验证客户端的身份凭证,而非安全端口使用明文HTTP协议,且默认不强制要求客户端提供任何身份凭证,此处设置相当于主动启用了这个“无加密、无强制认证”的端口,导致可以绕过API Server最基础的TLS加密和凭证校验机制,无需处理HTTPS证书验证,也无需准备合法的身份凭证,只需直接向8080端口发送明文HTTP请求,就能与API Server建立通信 -
--insecure-bind-address=0.0.0.0:这个参数决定了8080端口的网络监听范围,如果该参数设为127.0.0.1,那么8080端口只能被API Server所在节点的本地进程访问,外部主机(包括集群内其他节点、外网主机)无法连接到该端口,但设为0.0.0.0后,8080端口会对外暴露到该节点的所有网络(如内网、公网),任何能访问该节点 IP的攻击者都能直接连接到8080端口
开启匿名访问:--anonymous-auth=true关闭授权校验:--authorization-mode=AlwaysAllow暴露不安全端口:--insecure-port=8080、--insecure-bind-address=0.0.0.0
漏洞验证
- 直接访问8080端口,可以未授权访问API接口信息
- 可以获取
service-account-token
-
还可以执行包括但不仅限于以下操作
-
工具下载:https://cdn.dl.k8s.io/release/v1.35.0/bin/windows/amd64/kubectl.exe
-
查询默认命名空间下所有Pod
- 查询集群所有节点
- 查询所有命名空间下的Pod
- 进入
default命名空间的escape-pod这个Pod执行bash命令
外部交流群(欢迎进群互相交流):由于群人数超过了200,只能邀请拉群,可以关注公众号,后台回复“加群”,获取助手绿泡泡,联系小助手进交流群
MINOR COLD
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:凌曦安全 Syst1m《2026了,打red的时候遇到K8S还不知道咋横向吗(上)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论