把 STRIDE 套到 Kubernetes 上
一句话总结
威胁建模不是凭感觉列出“什么可怕”,而是使用分类体系进行无遗漏检查。把 STRIDE 六类威胁对应到 Kubernetes 对象上,检查项便会自然产生。
为什么需要它
安全审查因人而异,是因为每个人只关注自己熟悉的威胁。网络人员看防火墙,开发人员看注入。STRIDE 提供一份检查清单,要求确认**“这六类问题是否全部问过”**,目的在于从结构上减少遗漏。
工作原理
六类威胁的 Kubernetes 对应形式
| STRIDE | 含义 | 在 Kubernetes 中的表现 | 主要应对措施 |
|---|---|---|---|
| Spoofing | 身份冒充 | 窃取 SA 令牌、伪造证书、使用 --as 冒充 |
强认证、缩短令牌生存期、控制 impersonate 权限 |
| Tampering | 篡改 | 替换镜像、直接写 etcd、操纵清单 | 镜像签名、控制 etcd 访问、GitOps |
| Repudiation | 抵赖 | 无法证明是谁操作 | 审计日志、独立身份(禁止共享账户) |
| Information Disclosure | 信息泄露 | Secret 泄露、kubelet 读取端口、日志中的凭据 | 静态存储加密、RBAC、日志卫生 |
| Denial of Service | 拒绝服务 | 资源耗尽、apiserver 洪泛、Webhook 故障 | ResourceQuota、LimitRange、PDB、API 优先级 |
| Elevation of Privilege | 权限提升 | privileged Pod、hostPath、RBAC 配置错误 | PSA、最小权限、准入策略 |
权限提升路径——KCSA 的核心
权限提升不是“直接获得管理员权限”,而是**“从非管理员权限通往管理员权限的路径”**。应记住以下四种典型路径。
1)pods/exec 或 pods/attach
能够进入 Pod,就能读取该 Pod 的 ServiceAccount 令牌。如果该 SA 比自己权限更高,就会完整获得它的权限。 为调试方便授予的权限,会变成通向“集群所有 SA 中最强者”的阶梯。
2)读取 secrets
Secret 可能包含其他 SA 的令牌、数据库凭据、外部 API 密钥。在某命名空间拥有 get secrets,就能读取其中所有 Secret。
3)对 rolebindings/clusterrolebindings 拥有 create
这可能允许主体为自己授予更高权限。Kubernetes 已考虑这种情况,默认会阻止用户授予自己本来不拥有的权限(防止权限提升)。下一项则是突破这一防御的能力。
4)escalate、bind、impersonate 动词
escalate——允许把自己不拥有的权限也写入 Role 的元权限bind——允许绑定自己并不拥有的 Roleimpersonate——冒充其他用户、组或 SA;能冒充system:masters就彻底结束了
Pod spec 本身也是权限提升路径。
privileged: true→ 实际等同于节点 root- 通过
hostPath挂载/→ 整个节点文件系统(包括 kubelet 证书) hostNetwork/hostPID→ 节点的网络与进程命名空间capabilities.add: [SYS_ADMIN]→ 一整套容器逃逸工具
“能够创建 Pod”在潜力上接近“能够拥有该节点”。 因此,使用 PSA 或策略引擎限制 Pod spec,与 RBAC 同样重要。
供应链威胁
无论集群锁得多严,对自己主动获取并运行的内容都无济于事。
- 基础镜像——直接带入有漏洞的库
- 标签漂移——
myapp:1.4.2在昨天和今天可能指向不同内容 - 依赖污染——typosquatting,或账户被盗后发布恶意版本
- 构建流水线——CI 拥有集群部署权限,因此 CI 失陷就等于集群失陷
- 构建参数残留——通过
--build-arg传入的秘密会完整出现在docker history --no-trunc。即使后续层删除文件,内容仍留在前一层;镜像一旦推送,所有拉取者都能读取
应对措施是确保来源与完整性:只允许可信镜像仓库、固定摘要、验证镜像签名,并通过 SBOM 列出其中内容。
建立持久性(persistence)的技术
攻击者入侵成功后,会留下再次进入的路径。整理这些路径,就能转化为检测项。
- 部署 DaemonSet——每个节点一个,新节点加入后自动跟随
- CronJob——周期性复活的后门
- 注册准入 Webhook——拦截所有对象创建并秘密修改(mutating)
- 添加 ClusterRoleBinding——使用不显眼的名称绑定 cluster-admin
- 获取 SA 令牌——创建长期令牌 Secret 后,即使删除账户也可能继续存活,尤其在
--service-account-lookup=false的集群中 - 静态 Pod——在节点清单目录放入文件,无需经过 apiserver 即可运行;在 kubectl 中会显示为正常的镜像 Pod
实际现场中的情况
作者博客总结的 RBAC 事故模式中,最常见的是发现“所有 ServiceAccount 都能读取集群资源”的异常状态。诊断方法是运行 kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin")',完整调查 cluster-admin 的绑定主体。这与检测持久性技术使用的是同一查询。
供应链方面还有更直观的案例:通过 docker build --build-arg NPM_TOKEN=... 传入的令牌,会原样出现在 docker history --no-trunc。即使在 RUN 阶段删除文件,内容仍留在前一层。 正确方法是使用 RUN --mount=type=secret,id=npmrc,... 这类构建秘密挂载。
作者对秘密泄露响应顺序的提醒也与威胁建模相连。最常见的反应是重写 Git 历史,但顺序错了。 推送到公开仓库的凭据会在数秒到数分钟内被自动扫描器收集;即使删除历史,仍会留在 fork、现有克隆、平台保留的 PR 引用、搜索缓存和 CI 制品中。必须先废止(revocation),历史清理只是减少再次发生的卫生工作。 这是威胁建模改变响应顺序的例子。
下一项测验要确认什么
本模块以测验结束。下一模块将学习实际阻止基于 Pod spec 权限提升的 PSA,并在实验中亲自确认违反 restricted 的 Pod 被拒绝。