Kubernetes 安全系列之: RBAC权限错误配置的隐患

130 阅读3分钟

背景

我们对K8S集群中的一些 Pod 已采取限制,以防止它们访问 API server。 然而,一位安全分析师刚刚报告说 Pod 仍然可以绕过现有的控制并查询 API。 本文将通过重现攻击来验证问题是否存在,并修复错误的配置。

假设,集群已部署的资源如下:

apiVersion: V1
kind: Secret
metadata:
  name: credentials
type: Opaque
data:
  credentials: UmllQ2v1zmkxSnV4NnZlaTlvaiZib3h1bTdhVGFpSDNtZNVtYwhraTBv
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: anon-rolebinding
subjects:
- kind: User
  name: system:anonymous
  apiGroup: rbac.authorization.k8s.10
roleRef:
  apiGroup:
  kind: Clusterole
  name: admin
---
apiversion: apps/v1
kind: Deployment
metadata:
  name: secured
spec:
  selector:
    matchlabels:
      name: secured
  replicas: 1
  template:
    metadata:
      labels:
      name: secured
    spec:
      automountServiceAccountToken: false
      containers:
      - name: secured
        image: sf-alpine
        imagePullPolicy: Never
        command: ["sh"]
        args: [ "-C", "exec sleep infinity" ]

从上文的yaml可以看到,我们分别定义了SecretClusterRoleBinding 以及一个Deployment 三种资源, 其中Deployment并未关联Secret, 然而我们将尝试在pod中获取到 secret的值, 即说明集群中确实存在安全隐患。

这里值得一提的是,在Depolyment中, 我们定义了 automountServiceAccountToken: false 的配置, 以禁用POD自动挂载 API credentials 以及l查询API服务器。具体含义可参考官方文档: kubernetes.io/docs/tasks/…

尝试攻击

Instructions

  • 首先, 进入到 secured Pod 并观察看看API credential 文件是否被挂载 。通常, POD 加载相关的ServiceAccount 的话,可以在pod /var/run/secrets/kubernetes.io/serviceaccount/token 查找到相应的service account token

在这里插入图片描述

可以看到,该 secured Pod 由于 已配置 automountServiceAccountToken option 为 false, 并未能查找到token文件

  • 接下来,我们尝试即使在没有credentials的情况下, 该pod也能访问到Kubernetes API 并获取集群中所有secrets的信息, 我们可以通过POD 中env环境变量中找到 Kubernetes API 的 IP 地址

在这里插入图片描述

  • 我们直接使用 curl命令 访问Kubernetes API URL, 并在/api/v1/namespaces/default/secrets 路径下获取secret 信息

在这里插入图片描述

在这里插入图片描述

可以看到,我们的Curl命令成功地从Kubernetes API返回了json 信息且看到我们在上文定义的secret。设想下若是攻击者已获取该pod的掌握权,通过简单的curl方式就能获取到集群中所有的credentials,会带来极大的安全隐患。

问题解决

既然我们在POD中已经定义了 automountServiceAccountToken: false 的配置, 以禁用POD自动挂载 API Credentials, 为何POD还是能访问API Server呢?

原因:

我们再来看看yaml配置, 原来在ClusterRoleBinding 配置中 将admin Role 赋给了 system:anonymous 这个user。要知道, 如果我们访问 API server的 secure-port端口时不带任何凭证的话,默认会被服务器标记为匿名请求,即使用system:anonymous用户的权限访问。

因此,我们试着删除这个错误的ClusterRoleBinding 配置,再来访问 KUBE API server 看看。

在这里插入图片描述 可以看到,这次我们的请求就会被拒绝了 ,返回了403的错误

总结:

即使在禁用POD自动挂载 API credential的情况下, 该Pod 仍可能使用宽松的 RBAC 规则来查询服务器的 API 并窃取机密。 因此,我们在定义RBAC 规则时候,需要格外注意权限是否过度暴露的情况。

原文链接: 关注公众号: 云原生SRE