4. Secrets安全威胁建模

在Kubernetes中,Secret是承载敏感信息的一等公民对象,但它本身并不是“安全保险箱”。理解Secret的安全威胁,需要先明确它的攻击面:Secret从创建到被消费,会经过API Server、etcd、kubelet、容器运行时、节点文件系统、环境变量、镜像层、日志与CI/CD流水线等多个环节。每一个环节都可能成为攻击者获取明文或间接推断敏感信息的入口。威胁建模的目标,就是把这些入口系统化地识别出来,并评估其被利用后可能造成的权限提升与横向移动风险。

一、攻击面分析:Secret的生命周期暴露点

Secret的典型生命周期是:用户或控制器通过kubectl、API或GitOps工具提交Secret对象 → API Server鉴权并写入etcd → 调度器将Pod调度到节点 → kubelet从API Server拉取Secret → kubelet将其写入节点本地存储(tmpfs或磁盘) → 容器运行时以volume或环境变量方式注入容器 → 应用读取并使用。这个链条上,攻击面可以归纳为四类:控制面暴露(API Server未授权访问、etcd未加密或备份泄露)、节点暴露(kubelet只读端口、节点本地Secret文件、容器运行时接口)、工作负载暴露(环境变量被进程转储、日志打印、镜像层残留)、供应链暴露(CI/CD变量、Helm values、Git仓库中的明文Secret)。

以etcd为例,默认情况下Secret以base64编码存储,并非加密。如果攻击者获得etcd的读权限或拿到etcd快照备份,所有Secret等同于明文。同样,如果API Server的--authorization-mode配置不当,或ServiceAccount被授予了过宽的get/list/watch secrets权限,攻击者可以直接读取整个命名空间的Secret。节点侧,kubelet会将Secret挂载到/var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~secret/下,若节点被入侵且未启用只读挂载或未限制节点访问,Secret文件可被直接读取。

Secret生命周期攻击面与STRIDE威胁映射 创建/提交 kubectl / GitOps / CI API Server 鉴权 / 准入 / 审计 etcd 存储 base64 / 加密配置 kubelet 拉取 节点本地缓存 容器消费 volume / env 明文入库 Git/Helm values CI变量泄露 越权读取 SA权限过宽 匿名访问 存储泄露 etcd快照 未加密磁盘 节点窃取 kubelet只读端口 本地文件读取 运行时泄露 env转储/日志 镜像层残留 STRIDE 威胁分类与Secret场景映射 S 仿冒 伪造SA Token 冒充合法客户端 访问API Server T 篡改 修改Secret内容 注入恶意凭据 污染下游服务 R 抵赖 无审计日志 无法追溯读取者 操作不可归因 I 信息泄露 env/日志输出 etcd快照外泄 镜像层残留 D 拒绝服务 删除关键Secret Pod无法启动 服务中断 E 权限提升 Secret→Token 横向移动 集群接管 典型权限提升链:读取Secret → 获取数据库/云凭据 → 访问外部系统 → 窃取ServiceAccount Token → 调用API Server → 创建特权Pod → 接管集群 防御重点:最小权限RBAC + 静态加密 + 审计日志 + 短期Token + 外部Secret管理

二、常见泄露途径与权限提升风险

Secret泄露最常见的途径并不是“被黑客攻破”,而是“被自己人无意暴露”。第一类是环境变量泄露:许多应用在启动时将Secret注入环境变量,而崩溃转储、/proc/<pid>/environ、调试端点或错误日志都可能把环境变量完整打印出来。第二类是镜像与代码仓库泄露:开发人员把kubectl create secret生成的YAML直接提交到Git,或在Dockerfile中通过ARG传入密钥,导致镜像层中残留明文。第三类是日志与监控泄露:应用把包含Secret的请求体、连接字符串或配置对象写入日志,日志又被采集到ELK或云日志服务中。第四类是备份与快照泄露:etcd备份、PV快照、CI缓存中可能包含未加密的Secret数据。

泄露本身不是终点,权限提升才是攻击者的目标。一个典型的提升链是:攻击者通过某个Pod的环境变量拿到数据库密码 → 连接数据库获取更多业务数据 → 在数据库中发现云厂商AccessKey → 使用AccessKey访问云API → 获取Kubernetes集群的kubeconfig或创建新的ServiceAccount Token → 调用API Server创建特权Pod → 挂载宿主机文件系统 → 接管整个集群。这条链上,Secret是起点,RBAC配置和Token有效期决定了攻击者能走多远。如果ServiceAccount Token是长期有效的,且绑定了cluster-admin或过宽的secrets get/list权限,攻击者可以在几分钟内完成从单点泄露到集群接管的跨越。

三、STRIDE方法在Secret治理中的应用

STRIDE是微软提出的威胁建模框架,包含六类威胁:仿冒(Spoofing)、篡改(Tampering)、抵赖(Repudiation)、信息泄露(Information Disclosure)、拒绝服务(Denial of Service)、权限提升(Elevation of Privilege)。将STRIDE映射到Secret场景,可以系统化地发现遗漏的威胁。例如,仿冒对应攻击者伪造ServiceAccount Token或冒充合法客户端访问API Server;篡改对应攻击者修改Secret内容,向应用注入恶意凭据;抵赖对应没有开启审计日志,无法追溯谁读取或修改了Secret;信息泄露对应上述所有泄露途径;拒绝服务对应攻击者删除关键Secret导致Pod无法启动;权限提升对应从Secret到Token再到集群接管的链条。

在实际操作中,可以按以下步骤对Secret做一次STRIDE威胁建模:第一步,画出数据流图,标出Secret的创建、存储、分发、消费四个阶段;第二步,对每个阶段逐一问六个问题——谁能仿冒?什么能被篡改?操作能否被抵赖?什么信息会泄露?什么会导致不可用?如何提升权限?第三步,为每个识别出的威胁记录现有控制措施和残余风险;第四步,输出缓解措施并排优先级。例如,针对“信息泄露”,缓解措施包括启用etcd静态加密、使用secretKeyRef替代环境变量、禁止在日志中打印Secret、对Secret访问开启审计;针对“权限提升”,缓解措施包括最小权限RBAC、使用短期Token、限制create pod权限、启用Pod Security Admission。

教学示例:假设某命名空间中有应用A,其ServiceAccount绑定了get secrets权限。攻击者通过应用A的日志拿到一个数据库密码,进而获取云AccessKey。若该AccessKey具备eks:DescribeCluster权限,攻击者可获取集群访问入口;若集群中又存在绑定cluster-admin的ServiceAccount且Token未过期,攻击者即可创建特权Pod。这个示例说明:Secret治理不能只看Secret本身,必须结合RBAC、Token生命周期和云权限一起建模。

四、威胁建模输出示例

下表给出一个可直接参考的STRIDE威胁建模记录表,字段包括威胁类型、攻击面、攻击场景、现有控制、残余风险和缓解措施。实际使用时,可按命名空间或应用逐个填写。

STRIDE类型 攻击面 攻击场景 现有控制 残余风险 缓解措施
仿冒 API Server 伪造SA Token访问API Token短期有效 中 启用TokenRequest、绑定受众
篡改 etcd / API 修改Secret注入恶意凭据 RBAC限制写权限 低 开启审计、使用准入控制
抵赖 审计日志 读取Secret后无记录 未开启审计 高 启用审计策略并集中存储
信息泄露 环境变量/日志 env转储或日志打印Secret 部分应用使用volume 高 统一改用volume挂载、日志脱敏
拒绝服务 Secret对象 删除关键Secret导致Pod失败 无备份 中 GitOps备份、RBAC限制删除
权限提升 SA Token / RBAC Secret→Token→特权Pod 部分SA权限过宽 高 最小权限、限制create pod、PSA

威胁建模不是一次性活动。每当新增应用、调整RBAC、更换Secret管理方案或引入新的CI/CD流水线时,都应重新审视攻击面和STRIDE映射。只有把Secret放回整个Kubernetes权限体系与供应链中去看,才能真正识别出那些“看起来只是一个密码”背后的系统性风险。