4. Kubernetes RBAC 权限过度授予检测

Kubernetes RBAC 权限过度授予检测 学习卡片

场景搭建:一个被过度授权的 ServiceAccount

RBAC 过度授予的典型形态是:ServiceAccount 通过 ClusterRoleBinding 绑定了 cluster-admin,或通过 RoleBinding 绑定了包含 * 动词、* 资源的宽泛 Role。下面先构造一个可复现的检测对象。

# 1. 创建命名空间与 ServiceAccount
kubectl create namespace rbac-lab
kubectl -n rbac-lab create serviceaccount over-priv-sa

# 2. 绑定 cluster-admin(模拟过度授权)
kubectl create clusterrolebinding over-priv-binding \
  --clusterrole=cluster-admin \
  --serviceaccount=rbac-lab:over-priv-sa

# 3. 再创建一个"看似收敛"但实际过宽的自定义 Role
kubectl -n rbac-lab create role wide-role \
  --verb=get,list,watch,create,delete \
  --resource=pods,secrets,configmaps,serviceaccounts
kubectl -n rbac-lab create rolebinding wide-binding \
  --role=wide-role \
  --serviceaccount=rbac-lab:over-priv-sa

此时该 SA 同时持有集群级全权与命名空间级宽泛写权限,是检测脚本需要同时命中的两类风险。

权限边界探测:kubectl auth can-i

kubectl auth can-i 支持以任意身份模拟查询,是判断"实际能做什么"最直接的手段。关键是用 --as 指定 SA 的完整用户名格式:system:serviceaccount:<namespace>:<name>。

SA="system:serviceaccount:rbac-lab:over-priv-sa"

# 集群级高危动作探测
kubectl auth can-i create clusterrolebindings --as="$SA"
kubectl auth can-i delete nodes               --as="$SA"
kubectl auth can-i '*' '*' --all-namespaces   --as="$SA"

# 命名空间级探测
kubectl auth can-i delete secrets -n rbac-lab --as="$SA"
kubectl auth can-i get pods --all-namespaces  --as="$SA"

# 列出该身份在全部命名空间下的全部权限(K8s 1.24+)
kubectl auth can-i --list --as="$SA" --all-namespaces

判读要点:yes 表示允许;no 表示无权限;no - <reason> 表示被显式拒绝规则拦截。若 create clusterrolebindings 返回 yes,说明该 SA 可自我提权,属于最高危信号。

结构化分析:rbac-tool 与权限图谱

kubectl auth can-i 是逐点探测,rbac-tool 则从集群整体视角枚举"谁对什么有什么权限",适合批量发现过度授权。

# 安装(Krew 方式)
kubectl krew install rbac-tool

# 1. 查看某 SA 的完整权限汇总
kubectl rbac-tool who-can get secrets
kubectl rbac-tool who-can '*' '*'

# 2. 导出全部 Role/ClusterRole 的权限矩阵
kubectl rbac-tool analysis --output json > rbac-analysis.json

# 3. 生成可视化权限图(输出 dot,可转 png)
kubectl rbac-tool viz --outformat dot > rbac.dot
dot -Tpng rbac.dot -o rbac.png

重点关注 who-can 结果中同时出现 cluster-admin 与普通 SA 的行,以及 analysis 输出里 rules 含 * 的条目。

RBAC 过度授权检测:对象—绑定—权限—风险 ServiceAccount rbac-lab / over-priv-sa ClusterRoleBinding over-priv-binding RoleBinding wide-binding (ns: rbac-lab) ClusterRole cluster-admin (* / *) Role wide-role (pods/secrets…) 探测与判读 kubectl auth can-i create clusterrolebindings --as=system:serviceaccount:rbac-lab:over-priv-sa → yes(可自我提权) kubectl auth can-i delete secrets -n rbac-lab --as=… → yes(命名空间内可删敏感数据) kubectl rbac-tool who-can '*' '*' → 命中 over-priv-sa 与 cluster-admin 同列 过度授权风险结论 高危:cluster-admin 绑定 → 集群全权,可创建/删除任意资源、读取全部 Secret 中危:wide-role 含 delete secrets / create pods → 可横向移动、窃取凭据

检测脚本:批量识别过度授权

把上述探测固化为脚本,对命名空间内所有 SA 逐一评估,输出风险清单。

#!/usr/bin/env bash
# rbac-overgrant-check.sh —— 检测命名空间内 SA 的过度授权
set -euo pipefail
NS="${1:-rbac-lab}"
HIGH_RISK_VERBS=("create" "delete" "update" "patch")
HIGH_RISK_RES=("clusterrolebindings" "rolebindings" "secrets" "nodes" "pods/exec")

echo "== 命名空间 $NS 下 ServiceAccount 权限审计 =="
for sa in $(kubectl -n "$NS" get sa -o jsonpath='{.items[*].metadata.name}'); do
  USER="system:serviceaccount:${NS}:${sa}"
  echo "--- SA: $sa ---"

  # 1. 是否具备集群级全权
  if kubectl auth can-i '*' '*' --all-namespaces --as="$USER" 2>/dev/null | grep -q '^yes'; then
    echo "  [HIGH] 拥有集群级 */* 权限(疑似 cluster-admin)"
  fi

  # 2. 高危动词 × 高危资源组合
  for v in "${HIGH_RISK_VERBS[@]}"; do
    for r in "${HIGH_RISK_RES[@]}"; do
      if kubectl auth can-i "$v" "$r" -n "$NS" --as="$USER" 2>/dev/null | grep -q '^yes'; then
        echo "  [MED ] 允许 $v $r"
      fi
    done
  done
done

运行方式:bash rbac-overgrant-check.sh rbac-lab。预期输出中,over-priv-sa 会同时命中 [HIGH] 与多条 [MED ],其余未绑定宽泛角色的 SA 应无输出。

结果判读与修复方向

检测信号含义建议动作
can-i '*' '*' = yes集群级全权移除 cluster-admin 绑定,改用最小权限 ClusterRole
can-i create clusterrolebindings = yes可自我提权禁止该动词,或改用受限 Role
can-i delete secrets = yes可破坏/窃取凭据收敛为只读或限定 resourceNames
rbac-tool who-can 命中多个 SA权限面过宽按职责拆分 Role,避免共享宽泛角色
检测脚本仅做权限探测,不修改集群对象。修复前请先确认该 SA 的实际调用方,避免误删导致业务中断。