3种攻击手段教你拿下k8s集群
一、概览
云原生技术架构在带来颠覆性技术架构变革的同时,也带来了新的安全要求和挑战。在过去几年以及未来数年内,云原生架构会成为黑客攻击和利用的重点。Kubernetes,简称k8s,是当前主流的容器调度平台,更被称为云原生时代的操作系统,可见其重要性。简单来说,k8s是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。本文从k8s用户授权方面来谈谈针对k8s集群渗透的手法,如有不足之处,还望各位老师傅进行斧正。
二、Kubernetes中的用户
Kubernetes 集群中包含两类用户:一类是由 Kubernetes 管理的 service account,另一类是普通用户。普通用户被假定为由外部独立服务管理。管理员分发私钥,用户存储(如 Keystone 或 Google 账户),甚至包含用户名和密码列表的文件。在这方面,Kubernetes 没有代表普通用户账户的对象。无法通过 API 调用的方式向集群中添加普通用户。
相对的,service account 是由 Kubernetes API 管理的账户。它们都绑定到了特定的 namespace,并由 API server 自动创建,或者通过 API 调用手动创建。Service account 关联了一套凭证,存储在 Secret,这些凭证同时被挂载到 pod 中,从而允许 pod 与 kubernetes API 之间的调用。
API 请求被绑定到普通用户或 serivce account 上,或者作为匿名请求对待。这意味着集群内部或外部的每个进程,无论从在工作站上输入 kubectl 的人类用户到节点上的 kubelet,到控制平面的成员,都必须在向 API Server 发出请求时进行身份验证,或者被视为匿名用户。
user
外部用户是 k8s 中非常常见的一种访问者身份,通常用于从 k8s 之外来访问集群中的资源。因为这种资源的定位就是外部用户,所以 k8s 是不会存储 User 信息的,我们可以通过 Keystone 或者 Google Accounts 这种外部应用来管理。
group
同外部用户,Group 也是一种外部的概念,在X509客户端证书认证的方式中,Group 名字就是证书的组织名(Orgnization)
service account
相对于外部用户 User 而言,Service Account 则是集群内部的用户,我们可以使用 k8s api 来查看和管理这种用户。
anonymous
当一个请求没有携带任何的认证信息时,它会自动获得用户名:system:anonymous和用户组system:unauthenticated,我们可以配置分配特定的权限给这种匿名用户,适用于想要公开一些不敏感的资源等场景。kubelet 10250 未授权访问、kube-apiserver 8080端口未授权访问,皆属于此种情况。
三、渗透思路
k8s api-server 8080未授权
部署在Master上暴露Kubernetes API,是Kubernetes的控制面。Kubernetes API服务器为API对象验证和配置数据,这些对象包含Pod,Service,ReplicationController等等。API Server提供REST操作以及前端到集群的共享状态,所有其他组件可以通过这些共享状态交互。默认情况,Kubernetes API Server提供HTTP的两个端口:8080,6443。insecure-port: 默认端口8080,在HTTP中没有认证和授权检查。secure-port :默认端口6443, 认证方式,令牌文件或者客户端证书,如下图访问http://IP:8080
渗透思路:通过未授权的8080端口,可以读写kube-apiserver的api,创建挂载根目录的特权DaemonSet实现控制集群的目的。
注:k8s DeamonSet会在集群中的每台机器上创建一个
2. kubelet 10250端口未授权
kubelet会在kubernetes集群中的每一个节点上运行一个实例,对容器进行生命周期的管理。kubelet开放的端口有:4194、10248、10250和10255。kubelet的10255端口提供了pod和node的信息。如果对外开放,攻击者利用公开api可以获取敏感信息。kubelet的10250端口是kubelet server 与 apiserver 通信的端口,定期请求 apiserver 获取自己所应当处理的任务,通过该端口可以访问获取node资源以及状态。如果kubelet的10250端口对外暴露,存在远程命令执行漏洞。
渗透手法:用curl直接连接kublet的10250端口: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"
3. Service acount 高权限账户的风险
k8s创建pod时,默认会把token、ca.crt、namespace三个文件挂载到pod内部,默认挂载到/run/secrets/kubernetes.io/serviceaccount目录, 如果挂载到集群内的token具有创建pod的权限,可以通过token访问集群的api创建特权容器,然后通过特权容器逃逸到宿主机,从而拥有集群节点的权限。如下图这种权限控制有较大的风险,可以直接拿到集群权限:(激进一点的举例,勿喷。相信各位运维小哥,不会犯这种错误。):
此种情况下有两种渗透方式:
调用k8s sdk创建特权容器、挂载根目录的容器
把kubectl 放到pod内,创建特权容器、挂载根目录的容器
四、总结
本文从k8s api-server 8080端口未授权访问、kubelet 10250端口未授权访问、rbac权限三方面不安全配置,介绍了渗透k8s集群的方法。渗透集群手法还有很多种,后文再表。
关于鲲鹏安全实验室
鲲鹏安全实验室专注于容器安全和业务灰黑产对抗的研究,收集和挖掘容器相关技术的安全漏洞,采集业务灰黑产情报,研究对抗手段。并将研究成功转换为产品和服务。
内容编辑:鲲鹏安全实验室 令狐冲 责任编辑:剁肉工
往期推荐