Eswlnk Blog Eswlnk Blog
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈
  • 注册
  • 登录
首页 › 渗透分析 › 对Kubernetes RBAC授权防御&攻击的部分思考

对Kubernetes RBAC授权防御&攻击的部分思考

Eswlnk的头像
Eswlnk
2023-07-10 12:46:37
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
智能摘要 AI
本文探讨了Kubernetes中的授权管理,分为基础设施和应用服务两类权限授予。基础设施权限通过用户账户管理,master节点使用admin权限,node节点使用受限权限。服务权限通过ServiceAccount管理,允许细粒度控制不同服务的资源访问。文中介绍了如何通过RoleBinding和ClusterRole为不同用户和服务分配特定权限,并展示了通过UserAccount和ServiceAccount实现权限分发的实践案例。最后提出在复杂业务场景中,如何进一步优化授权流程以提高效率和安全性的问题。

写在前面

不久前看到一篇对Kubernetes授权管理的文章,笔者而后进行一些实验和思考,因此诞生了这篇学习笔记。本文章思路未必贴合实际应用场景,有概念错误的地方还望多多指正。

首先笔者对于Kubernetes用户的授权分为两个主体:对基础设施的权限授予和对服务的权限授予

分类讨论

0x01-基础设施

基础设施的权限,理想情况下按照集群结构划分:

  • master节点使用admin用户账户权限,这个权限是最大的
  • node节点使用普通用户权限,普通用户权限仅能对集群中的部分资源控制,或者是对某个namespcace中的资源进行控制

0x02-服务

什么叫做对服务进行划分呢?云计算的初衷是优雅地调配庞大规模的服务群,那么运维人员就需要对A、B、C…这些服务(Service)能够操纵集群权限这个能力进行考量,假如Service A由三台nginx容器构成,可能就不需要什么集群服务的资源。对于B服务而言,其定位是用来监控集群主机健康状态的,所以就需要很强的CURD权限,起码是对Pod、Deployment有管理权限。

在Kubernetes中,每个服务容器都会被kubelet下发一个默认的ServiceAccount账户(后文简称SA),而运维人员可以指定服务容器注入哪个SA账户。这意味着运维人员可以将不同SA账户注入给各类服务容器,来达到各类服务(A、B、C)权限细粒度化。

0x03-归根到底

基础设施和服务的权限授予有相同之处,但又不完全相同。它们相同的地方在于概念,都是为了控制对集群资源操纵的能力,这一过程在Kubernetes中叫做授权(Authoriazation),可以参考下图;不同的地方在于控制单元,基础设施的权限是以用户账户(User Account)的权限为单位的,而服务的权限是以SA账户(ServiceAccount)为单位划分的。

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

例如管理员事先建立Pod-read-Rule、Pod-Write-Rule规则,分别用来制约对Pod容器可读、可写这两种操作,当然集群的资源可不止有Pod容器,我们可以通过kubectl api-resources例举哪些资源可以被ClusterRole约束。
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
而后,通过RoleBinding或者ClusterBinding的方式将这两个ClusterRole分发给不同的User Account或者ServiceAccount,相当于是把锅碗瓢盆给到不同的角色。

假设一个场景,当User Account A需要拥有所有Pod的可读权限,那么管理员(kubernetes admin)就通过RoleBinding的形式将Pod-read-Rule绑定给User Account A;当User Account A再想要要所有Pod的可写权限时,以相同的RoleBinding方式将Pod-Write-Rule绑定给User Account A即可。

最终,我们创建一个理想化的场景:把集群内所有可利用资源(api-resources)的CURD操作分别建立为不同的ClusterRole,在创建Service Account与User Account时赋予它们最小权限,指定最少范围的namespace,最好只作用于default namespcace。而后当SA或者UA需要对应权限时,管理员再经过审核制RoleBinding,分配ClusterRole给这些SA或者UA,而不是在初始化时就把权限塞满。

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

实践

下面以两个实践为例,理解前文提到的权限分发思路。表格为实验拓扑:一台Centos7.x作为Master节点,剩下两台作为Node节点

主机IP地址内核版本用户账户
k8s-master192.168.56.803.10.0-1160.el7.x86_64kubernetes-admin
k8s-node1192.168.56.813.10.0-1160.el7.x86_64userA
k8s-node2192.168.56.823.10.0-1160.el7.x86_64userB

实践场景1-使用UserAccount

master节点使用kubernetes-admin用户进行管理,其他两个node节点使用userA、userB用户进行管理,且需要满足的条件:

  • kubernetes-admin具有对集群操纵的全部权限
  • userA用户仅拥有对tenantA命名空间的Pod容器完全操作权限
  • userB用户仅拥有对tenantB命名空间的Pod容器完全操作权限

分析:由于master节点的用户配置文件/etc/kubernetes/admin.conf默认为kubernetes-admin权限,所以我们无需关心,只需满足UserA、B的需求。

第一步:建立两个Kubernetes User Account分别为userA、userB,参考文章:k8s创建用户账号——User Account – fat_girl_spring – 博客园 (cnblogs.com)。完整的创建过程如下,以相同的方式创建两个用户即可

[root@k8s-master tenantA]# (umask 077;openssl genrsa -out userA.key 2048)
[root@k8s-master tenantA]# openssl req -new -key userA.key -out userA.csr -subj "/O=k8s/CN=userA"
[root@k8s-master tenantA]# openssl  x509 -req -in userA.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out userA.crt -days 365

[root@k8s-master tenantA]# kubectl config set-cluster k8s --server=https://192.168.56.80:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/root/k8s_tenants/userA/userA.conf

[root@k8s-master tenantA]# kubectl config set-credentials userA --client-certificate=userA.crt --client-key=userA.key --embed-certs=true --kubeconfig=/root/k8s_tenants/userA/userA.conf

[root@k8s-master tenantA]# kubectl config set-context kubernetes-userA@k8s --cluster=k8s --user=userA --kubeconfig=/root/k8s_tenants/userA/userA.conf

[root@k8s-master tenantA]# kubectl config use-context kubernetes-userA@k8s --kubeconfig=/root/k8s_tenants/userA/userA.conf

[root@k8s-master tenantA]# kubectl get pods --kubeconfig ./userA.conf

第二步:创建两个namespace给userA、userB使用,这里笔者模拟的场景是租户根据namespace隔离

[root@k8s-master ~]# kubectl create namespace tenant-a
namespace/tanent-a created
[root@k8s-master ~]# kubectl create namespace tenant-b
namespace/tanent-b created

第三步:创建ClusterRole描述Pod容器完全操作权限

# cluster_pod_all_permission_role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-pod-all-permission-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch", "create", "update", "delete"]

第四步:分别将cluster-pod-all-permission-role权限绑定给用户A/B,并指定相对应的命名空间

# usera_pod_rolebiding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tenanta-pod-all-permission-role-binding
  namespace: tenant-a
subjects:
- kind: User
  name: userA
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-pod-all-permission-role
  apiGroup: rbac.authorization.k8s.io
---
# userb_pod_rolebiding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tenantb-pod-all-permission-role-binding
  namespace: tenant-b
subjects:
- kind: User
  name: userB
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-pod-all-permission-role
  apiGroup: rbac.authorization.k8s.io

没有看错,我们使用的是RoleBinding而不是ClusterRolebinding来完成权限绑定。前文提到,RoleBinding是对某个namespace进行的权限绑定,而ClusterRolebinding是对整个集群做权限绑定,可以在RoleBinding时可以通过roleRef引用ClusterRolebinding,从而将集群的限制策略转为对namespace的权限绑定

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

第五步:使用kubectl apply描述资源对象,就能向userA、userB赋予了两个不同namespace的Pod完全执行权限,过程如下:

[root@k8s-master clusterrole]# kubectl apply -f cluster_pod_all_permission_role.yaml 
clusterrole.rbac.authorization.k8s.io/cluster-pod-all-permission-role created

[root@k8s-master clusterrole]# kubectl apply -f user_pod_rolebind.yaml 
rolebinding.rbac.authorization.k8s.io/tenanta-pod-all-permission-role-binding unchanged
rolebinding.rbac.authorization.k8s.io/tenantb-pod-all-permission-role-binding created

最后:我们来验证一下两个用户是否只能在当前租户空间(namespace)中操作Pod容器。如下图所示,k8s-node1使用userA作为用户账户,k8s-node2使用userB作为用户账户,它们仅能操作自身所在的namespace,除此之外无法访问任何namespace

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

实践场景2-使用ServiceAccount

在真实的渗透场景中,攻击者大多是通过Web网站拿到了某台容器的控制权限。在Kubernetes集群中,每台容器在启动时会被注入default权限的ServiceToken,位置在/var/run/secrets/kubernetes.io/serviceaccount,它是ServiceAccount(后文简称SA)的凭证

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

为了展示较大权限的SA都能做哪些事情,现在我们在tanent-a命名空间下创建一个Thinkphp Web Service,对外暴露30080端口。其Pod容器使用的SA定义为phpsa,并且phpsa具有对当前tanent-a命名空间下Pod完全执行权限。

创建Service

第一步创建phpsa,并且赋予其tanent-a命名空间下对Pod容器完全执行权限

#phpsa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: phpsa
  namespace: tenant-a

---
apiVersion: rbac.authorization.k8s.io/v1  
kind: RoleBinding
metadata:
  name: phpsa-role-binding
  namespace: tenant-a
subjects:
- kind: ServiceAccount
  name: phpsa
  namespace: tenant-a
roleRef:
  kind: ClusterRole
  name: cluster-pod-all-permission-role
  apiGroup: rbac.authorization.k8s.io

第二步,通过如下资源描述文件创建漏洞环境的Deployment,将其暴露为Service服务。指定Pod容器默认注入的SA账户为phpsa

apiVersion: apps/v1
kind: Deployment
metadata:
  name: thinkphp5023-rce
  namespace: tenant-a
  labels:
    app: thinkphp5023-rce
spec:
  replicas: 2
  selector:
    matchLabels: # 跟template.metadata.labels一致
      app: thinkphp5023-rce
  template:
    metadata:
      labels:
        app: thinkphp5023-rce
    spec:
      containers:
      - name: thinkphp5023-rce-container
        image: vulhub/thinkphp:5.0.23
        ports:
        - containerPort: 80
          name: thinkphp-port
      serviceAccount: phpsa

---
apiVersion: v1
kind: Service
metadata:
  name: thinkphp5023-vulnerable-service
  namespace: tenant-a
spec:
  type: NodePort
  selector: # 更Deployment中的selector一致
    app: thinkphp5023-rce
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 80
      name: thinkphp-port
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30081
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

到这里,一个具有RCE漏洞的thinkphp5.0.23版本就搭建完毕了,攻击者可以通过thinkphp5.xRCE漏洞建立reverse shell或上传webshell

后渗透利用

假设我们已经拿到thinkphp服务的容器权限,那么在后续的实战中,攻击者大多通过cdk等工具枚举当前SA账户phpsa都具有哪些权限

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
但cdk做的事情比较有限,如下图cdk代码段所示,它通过访问api/v1/namespaces端点来断言自己是否拥有list namespaces权限,但却没有甄别当前SA账户处于哪个namespace下。
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
由于当前容器的服务账号为phpsa,具备cluster-pod-all-permission-role权限,理论上拥有tenant-a命名空间下Pod容器完全执行权限,如果仅用cdk当脚本小子,无疑浪费大好的攻击机会。

但话说回来,攻击者在此面临两个问题:

  1. 盲视野攻击的状态下我们怎么能知道当前SA可以操作哪些命名空间呢?
  2. 如何确定SA账户所在的命名空间呢?

对于第一个问题,笔者暂时没有找到很好的解决方案。而第二个问题有一种取巧的解决方法:当我们尝试去访问api server中任何越权的操作端点时,api server会返回serviceaccount:x:y cannot list resource错误,此时x代表当前SA账户所在的namespace,y就代表当前SA账户的用户名

对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog
提取当前SA账户的namespace所属为tenant-a,接着就能列出命名空间tenant-a中的所有容器,也能进行后续的渗透操作

curl --cacert ./ca.crt --header "Authorization: Bearer $(cat ./token)" -X GET https://kubernetes.default.svc/api/v1/namespaces/tenant-a/pods
对Kubernetes RBAC授权防御&攻击的部分思考-Eswlnk Blog

写在最后

本文对理想条件下的Kubernetes授权进行了部分探究,但笔者比较好奇的是,业务态较广的云上业务,服务账号的授权行为不可能做到如此细粒度。那么有没有更快、更安全的做法将user group、namespace、准入控制玩出花活儿,从而让授权过程扁平化一些?先埋一个坑,等笔者有时间再探究一下

本站默认网盘访问密码:1166
本站默认网盘访问密码:1166
声明:本站原创文章文字版权归本站所有,转载务必注明作者和出处;本站转载文章仅仅代表原作者观点,不代表本站立场,图文版权归原作者所有。如有侵权,请联系我们删除。
kubernetes安全授权漏洞软件
0
0
Eswlnk的头像
Eswlnk
一个有点倒霉的研究牲站长
赞赏
360白文件识别以及白名单
上一篇
Linux内核存在条件竞争漏洞 | 黑客可获取root权限
下一篇

评论 (0)

请登录以参与评论
现在登录
    发表评论

猜你喜欢

  • 「漏洞资讯」CVE-2025-12914:宝塔面板曝出注入漏洞
  • 「亲测有效」Google Gemini 学生优惠:解决身份验证和支付卡验证
  • 今日热点:伪Clash软件下载陷阱曝光,附防范建议
  • 漏洞资讯:Ollama 未授权访问漏洞分析与防护指南
  • 「攻防对抗」利用 fastjson 原生反序列化与动态代理突破安全限制
Eswlnk的头像

Eswlnk

一个有点倒霉的研究牲站长
1108
文章
319
评论
679
获赞

随便看看

关于大多数网络验证的通用“解决”思路
2021-10-05 2:00:29
深入浅出”P牛”版CC1链
2022-03-27 22:32:25
腾讯云 Lighthouse 同地域组建 Kubernetes 集群
2023-10-16 22:34:04

文章目录

专题展示

WordPress53

工程实践37

热门标签

360 AI API CDN java linux Nginx PDF PHP python SEO Windows WordPress 云服务器 云服务器知识 代码 免费 安全 安卓 工具 开发日志 微信 微软 手机 插件 攻防 攻防对抗 教程 日志 渗透分析 源码 漏洞 电脑 破解 系统 编程 网站优化 网络 网络安全 脚本 苹果 谷歌 软件 运维 逆向
  • 首页
  • 知识库
  • 地图
Copyright © 2023-2025 Eswlnk Blog. Designed by XiaoWu.
本站CDN由 壹盾安全 提供高防CDN安全防护服务
蜀ICP备20002650号-10
页面生成用时 1.062 秒   |  SQL查询 28 次
本站勉强运行:
友情链接: Eswlnk Blog 网站渗透 倦意博客 特资啦!个人资源分享站 祭夜博客 iBAAO壹宝头条
  • WordPress142
  • 网络安全64
  • 漏洞52
  • 软件52
  • 安全48
现在登录
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈