威胁建模基础:STRIDE模型、威胁树分析、攻击面分析

威胁建模这件事,说白了就是在攻击者动手之前,先替他们想好怎么搞破坏。我做了这么多年安全,见过太多团队上线前拍胸脯说"没问题",结果上线第一周就被打穿。嗯,今天咱们就把这套方法论掰开揉碎讲清楚。

为什么需要威胁建模?

你想想看,一个系统从设计到上线,中间有多少环节可能出问题?代码漏洞、配置错误、权限遗漏……如果等到上线后再去修,成本至少翻十倍。我个人习惯是在架构设计阶段就拉上开发、运维、产品一起过一遍威胁建模。说白了,就是花半天时间,省下后面几个通宵。

核心观点:威胁建模不是安全团队的独角戏,而是整个研发流程的必修课。越早做,成本越低,效果越好。

STRIDE模型:六类威胁的思维框架

STRIDE 是微软提出的一套威胁分类方法,名字来自六类威胁的首字母。我在项目中遇到过不少团队,一上来就想着怎么防,结果连要防什么都说不清楚。STRIDE 就是帮你把"要防什么"先理清楚。

威胁类型 英文 核心问题 典型场景
S - 身份欺骗 Spoofing 攻击者能否冒充他人身份? 伪造 JWT Token、盗用 Session
T - 篡改 Tampering 数据是否可能被非法修改? 中间人篡改请求参数、数据库注入
R - 抵赖 Repudiation 用户能否否认做过某操作? 缺少审计日志、日志被删除
I - 信息泄露 Information Disclosure 敏感数据是否可能被窃取? API 返回明文密码、日志打印 Token
D - 拒绝服务 Denial of Service 系统能否被耗尽资源? CC 攻击、未限流的文件上传
E - 权限提升 Elevation of Privilege 低权限用户能否获得高权限? 水平越权、垂直越权

我的经验:刚开始用 STRIDE 时,容易把每个威胁都列得特别多。后来我发现,每个组件只关注最致命的 2-3 个威胁就够了。比如一个只读的日志服务,你非要去分析身份欺骗,意义不大。

威胁树分析:把威胁拆到原子级别

STRIDE 帮你找到"有什么威胁",但每个威胁怎么发生的?这就需要威胁树了。威胁树本质上是一棵 AND/OR 树,根节点是最终威胁,子节点是达成威胁所需的条件。

举个例子,假设我们分析"攻击者篡改更新包"这个威胁:

威胁:篡改更新包
├── OR ── 传输过程中被篡改
│   ├── 未使用 HTTPS
│   └── HTTPS 证书验证被绕过
└── OR ── 存储过程中被篡改
    ├── 存储服务器被入侵
    └── 内部人员恶意修改

为什么要拆到这么细?因为每个叶子节点都对应一个具体的防御措施。比如"未使用 HTTPS"这个叶子,对应的措施就是"强制全链路 HTTPS"。我曾经在一个项目中,团队说"我们用了 HTTPS 所以安全了",结果威胁树一拆,发现证书验证逻辑写错了——嗯,这就是拆到原子级别的价值。

避坑指南:威胁树不要画得太深。我见过有人把一棵树画了七八层,最后发现最底层的节点根本没法防御。建议控制在 3-4 层,每个叶子节点必须能对应到一个具体的控制措施。

攻击面分析:找到所有入口和出口

攻击面,说白了就是系统暴露给外部的所有接口。你想想看,一个系统如果有一百个 API 接口,其中九十九个都做了鉴权,就漏了一个——那攻击者肯定走那个漏的。攻击面分析就是帮你把这一百个接口全部找出来,一个都不能少。

我个人习惯把攻击面分成三类:

  • 网络攻击面:开放的端口、暴露的 API、Web 页面、WebSocket 连接
  • 软件攻击面:第三方库、SDK、插件、动态加载的模块
  • 人为攻击面:运维后台、管理控制台、内部工具、调试接口

这里有个很容易踩的坑——很多人只关注网络攻击面,觉得"端口没开就安全了"。但软件攻击面和人为攻击面往往更致命。我记得有一次做安全审计,发现一个系统所有对外端口都关了,但内部有个调试用的 GraphQL 接口没做鉴权,攻击者通过内网横向移动直接拿到了全部数据。

三者如何配合使用?

STRIDE、威胁树、攻击面分析不是三个独立的东西,而是一套组合拳。我一般这样用:

  1. 先画攻击面:把系统的所有入口、出口、数据流画出来。这是基础,没有这个后面都是空谈。
  2. 再用 STRIDE 分类:对每个入口和数据流,用 STRIDE 六类威胁过一遍,找出可能的风险点。
  3. 最后用威胁树深挖:对高风险点,用威胁树拆到原子级别,找到具体的防御措施。

下面这张图展示了三者的关系:

威胁建模三件套:配合关系 攻击面分析 找出所有入口和出口 STRIDE 模型 六类威胁分类 威胁树分析 拆解到原子级别 工作流程 先画攻击面 → 再用 STRIDE 分类 → 最后用威胁树深挖高风险点 输出:威胁清单 + 防御措施表 每个叶子节点必须对应一个具体的控制措施 控制措施包括:加密、鉴权、限流、审计、校验等 示例:攻击面发现 /api/update 接口 → STRIDE 识别为篡改威胁 → 威胁树拆解 → 措施:签名校验 + HTTPS

实战中的常见误区

做了这么多年安全审计,我总结了几条新手最容易踩的坑:

  • 只做一次威胁建模:系统是活的,威胁也是活的。每次迭代、每次架构变更,都应该重新过一遍。
  • 威胁清单太长:什么都想防,结果什么都防不住。我建议每个组件只关注 Top 3 威胁。
  • 忽略第三方依赖:你代码写得再安全,引了一个有漏洞的库,等于白干。威胁建模一定要覆盖第三方组件。
  • 只关注技术不关注流程:比如运维人员能不能直接修改生产数据库?这属于人为攻击面,但很多人会漏掉。

我曾经踩过的坑:有一次做威胁建模,团队把攻击面分析做得特别细,STRIDE 也过了一遍,但漏掉了"内部人员"这个维度。结果上线后,一个离职员工用之前没回收的 API Key 删了一批数据。从那以后,我每次都会专门问一句:"内部人员能做什么?"

小结

威胁建模不是一次性的文档工作,而是贯穿整个研发周期的思维方式。STRIDE 帮你分类、威胁树帮你深挖、攻击面分析帮你兜底。三者配合好了,你就能在攻击者动手之前,先把他们的路堵死。

嗯,这一章的内容就到这儿。记住一句话:安全不是防住所有攻击,而是让攻击的成本远大于收益。威胁建模就是帮你找到那个"成本最低的防御点"。