威胁建模基础:从“拍脑袋”到“有章法”

说实话,我见过太多团队做安全的方式了。需求评审时问一句“这个功能安全吗?”,大家面面相觑,最后说“应该没问题吧”。然后呢?上线后被薅羊毛、被越权、被注入,再紧急修复。

这种“拍脑袋”式的安全,说白了就是靠运气。而威胁建模,就是要把运气变成确定性。我做了十几年安全架构,最深的体会就是:没有威胁建模的项目,就像蒙着眼睛过马路。

核心观点:威胁建模不是“做不做”的问题,而是“什么时候做、怎么做”的问题。越早做,成本越低;越晚做,代价越高。

威胁建模的目的与价值

先问个问题:你为什么要做威胁建模?

我个人习惯把威胁建模的价值归纳为三点:

  • 提前发现风险——在代码还没写、架构还没定死的时候,就把可能出问题的地方找出来。我在项目中遇到过,一个支付系统的架构评审,威胁建模发现“订单金额在客户端计算”这个设计缺陷,改起来只花了半天。要是上线后才发现,那得动多少代码?
  • 统一团队认知——开发、测试、产品、安全,大家对“什么是安全的”理解往往不一样。威胁建模提供了一个共同的语言和框架,让所有人站在同一页上。
  • 降低修复成本——这个道理很简单:设计阶段改一个架构决策,成本是1;开发阶段改代码,成本是10;上线后修复漏洞,成本是100。威胁建模就是帮你把成本锁定在1的阶段。

我的经验:威胁建模最大的价值不是“找出所有威胁”,而是“让团队开始思考安全”。很多团队做完第一次威胁建模后,开发同学会主动说:“这个接口是不是应该加鉴权?”——这种意识上的转变,比任何工具都重要。

STRIDE模型详解

说到威胁建模,就绕不开STRIDE。这是微软提出的一套威胁分类模型,名字由六种威胁类型的首字母组成。

我刚开始学STRIDE时,总觉得它就是个分类标签。后来用多了才发现,STRIDE的真正价值是提供了一个“检查清单”——你对着这六类去审视系统,基本不会漏掉什么。

威胁类型 英文 核心问题 典型场景
S 欺骗 Spoofing 谁能假装成别人? 伪造用户身份、伪造服务器
T 篡改 Tampering 数据能被非法修改吗? 修改请求参数、篡改数据库
R 抵赖 Repudiation 做了事能赖账吗? 缺少操作日志、日志可被删除
I 信息泄露 Information Disclosure 敏感数据能被看到吗? 明文传输密码、API返回过多信息
D 拒绝服务 Denial of Service 系统能被搞瘫痪吗? 流量攻击、资源耗尽
E 权限提升 Elevation of Privilege 普通用户能干管理员的事吗? 越权操作、未授权访问

你想想看,这六类几乎覆盖了所有常见的安全问题。我在做威胁建模时,习惯把每个组件、每条数据流都过一遍STRIDE,就像安检一样,一个一个查。

注意:STRIDE不是银弹。它更适用于“应用层”的威胁分析,对于物理安全、社会工程学等场景,需要结合其他模型。我曾经在一个IoT项目中只用了STRIDE,结果漏掉了“设备被物理拆解”的风险——后来补了攻击树分析才补上。

威胁建模的流程

理论说完了,咱们来点实操。威胁建模的流程,我一般分成五步。这五步不是死规矩,但新手照着做,基本不会跑偏。

第一步:定义范围

这一步最容易被忽略。很多人上来就画图、找威胁,结果发现讨论了半天,连“这个系统到底包含哪些模块”都没对齐。

定义范围要回答三个问题:

  • 我们要分析的系统是什么?(边界在哪?)
  • 谁在使用这个系统?(用户角色有哪些?)
  • 系统依赖哪些外部服务?(第三方API、数据库、缓存等)

我个人习惯用一张简单的表格来记录范围定义的结果:

维度 内容
系统名称 用户订单服务
边界 从API网关到数据库,不包括前端页面
用户角色 普通用户、商家、管理员
外部依赖 支付网关、短信服务、物流API

第二步:分解系统

范围定好了,接下来就是把系统拆开,看清楚里面到底有什么。这一步的核心产出是数据流图(DFD)。

数据流图要画清楚:

  • 外部实体(用户、第三方系统)
  • 处理过程(业务逻辑模块)
  • 数据存储(数据库、缓存、文件)
  • 数据流(数据怎么流动的)
  • 信任边界(哪里是可信的,哪里是不可信的)

嗯,这里要注意:信任边界是威胁建模的关键。数据每跨一次信任边界,就可能引入新的威胁。比如用户请求从公网进入内网,这就是一次信任边界的跨越。

威胁建模流程与STRIDE关系图 威胁建模五步流程与STRIDE模型 定义范围 分解系统 识别威胁 确定风险 制定缓解措施 迭代 STRIDE 威胁分类 S - 欺骗 (Spoofing) T - 篡改 (Tampering) R - 抵赖 (Repudiation) I - 信息泄露 (Information Disclosure) D - 拒绝服务 (Denial of Service) E - 权限提升 (Elevation of Privilege) 关键要点 • 威胁建模是迭代过程,不是一次性活动 • STRIDE 在“识别威胁”阶段使用,作为检查清单 • 数据流图(DFD)是分解系统的核心产出 • 信任边界是威胁分析的关键切入点 • 风险确定后,缓解措施要可落地、可验证

第三步:识别威胁

系统分解好了,数据流图画出来了,接下来就是对着STRIDE,一个一个找威胁。

我常用的方法是:对每个数据流、每个处理过程、每个数据存储,都问一遍STRIDE的六个问题。比如:

  • 这个数据流会不会被篡改?
  • 这个处理过程会不会泄露用户信息?
  • 这个数据存储会不会被DoS攻击?

我曾经在一个电商项目中,用这个方法找出了37个潜在威胁。其中有一个是“用户下单时,订单金额在客户端计算后提交”——这就是典型的篡改威胁。后来我们改成了服务端计算金额,堵住了这个漏洞。

小技巧:识别威胁时,不要只盯着技术层面。业务逻辑上的威胁往往更隐蔽。比如“优惠券可以无限叠加使用”,这属于业务逻辑漏洞,但STRIDE里的“篡改”和“权限提升”都能覆盖到。

第四步:确定风险

威胁找出来了,但不可能全部修复。资源有限,时间有限,你得知道哪些威胁最要命。

确定风险,我一般用两个维度:可能性和影响程度。简单来说:

  • 可能性高 + 影响大 = 优先处理
  • 可能性低 + 影响小 = 可以接受
  • 其他情况 = 根据实际情况权衡

你可以用一张风险矩阵表来记录:

威胁描述 可能性 影响程度 风险等级 处理策略
用户可篡改订单金额 高 高 严重 立即修复
日志记录不完整 中 中 中等 计划修复
API返回过多用户信息 低 高 中等 评估后修复

第五步:制定缓解措施

最后一步,也是最实在的一步——怎么修?

缓解措施要具体、可落地。不要写“加强安全防护”这种废话,要写“在订单接口增加服务端金额校验”、“所有API响应中移除用户手机号字段”。

我个人习惯把缓解措施分成三类:

  • 设计层面——比如修改架构、增加鉴权层、引入加密
  • 技术层面——比如加WAF、做输入校验、加限流
  • 管理层面——比如增加安全评审、做渗透测试、培训开发人员

避坑指南:我曾经在一个项目中,团队花了两周时间做威胁建模,找出了20多个威胁,但最后只修复了5个。为什么?因为缓解措施写得太模糊,开发不知道怎么做。后来我改了做法:每个威胁必须对应一个具体的、可验证的缓解措施,并且指定负责人和截止时间。这样才真正落地。

总结一下

威胁建模不是什么高深的技术,它就是一个结构化的思考过程。你不需要成为安全专家,只要掌握STRIDE和五步流程,就能把安全从“拍脑袋”变成“有章法”。

嗯,最后说一句:威胁建模不是一次性的活动。系统在变,业务在变,威胁也在变。我建议每个大版本迭代都做一次威胁建模,哪怕只是快速过一遍,也比不做强。