威胁建模入门:从“拍脑袋”到“有章法”

很多团队做安全,上来就翻漏洞库、找工具扫描。结果呢?修了一堆低危问题,核心业务逻辑却被人绕过去了。我见过太多这样的案例了。

威胁建模,说白了就是在系统还没写一行代码之前,先坐下来画张图,想想“谁会攻击我?从哪下手?”。它不是玄学,是一套结构化的思考方法。今天我们就把它拆开揉碎了讲清楚。

一、威胁建模到底是什么?

我个人习惯把威胁建模理解成“安全领域的架构评审”。它不关注具体的漏洞(比如 SQL 注入),而是关注系统里哪些组件、哪些数据流、哪些信任边界可能出问题。

举个例子。你设计了一个用户登录模块。如果只靠经验,你可能会说“嗯,密码要加密”。但用威胁建模,你会问:

  • 密码在传输过程中会不会被截获?
  • 数据库被拖库了怎么办?
  • 攻击者能不能绕过登录直接访问后台接口?

你看,思考的维度完全不一样了。

核心要点:威胁建模 = 系统架构 + 攻击者视角 + 结构化分析。它不是一次性的,应该伴随整个设计、开发、测试周期。

二、STRIDE 模型详解:微软的“六脉神剑”

STRIDE 是微软提出的一套威胁分类模型。我刚开始用的时候觉得它太抽象,后来发现,它其实是把攻击者的手法分成了六类。你对着这六类去检查系统,基本不会漏掉大方向。

缩写 威胁类型 通俗理解 典型场景
S Spoofing(假冒) 冒充别人身份 伪造 JWT Token、盗用 Session
T Tampering(篡改) 修改不该动的东西 篡改请求参数、修改数据库记录
R Repudiation(抵赖) 做了不承认 用户说“我没下单”,但系统没日志
I Information Disclosure(信息泄露) 不该看的被看到了 API 返回了用户手机号、密码明文
D Denial of Service(拒绝服务) 让系统没法用 刷验证码接口、耗尽连接池
E Elevation of Privilege(权限提升) 普通用户干管理员的事 越权访问后台、水平越权看别人订单
我的小技巧:每次画完数据流图,我就拿 STRIDE 六类挨个问一遍每个数据流和每个存储节点。问完基本能覆盖 80% 的威胁。剩下的 20% 靠经验和对业务的理解去补。

三、数据流图(DFD):威胁建模的“地图”

没有地图,你怎么知道敌人从哪来?DFD 就是这张地图。它不关心代码细节,只关心数据怎么流动、谁在处理数据、数据存在哪。

DFD 有四个基本元素,我习惯用颜色来区分,这样画出来一目了然:

  • 外部实体(External Entity):人、外部系统。数据从这来,或到这去。
  • 过程(Process):对数据做处理的组件。比如登录服务、支付网关。
  • 数据存储(Data Store):数据休息的地方。比如数据库、缓存、文件。
  • 数据流(Data Flow):数据移动的路径。用箭头表示方向。

画 DFD 有个关键点:信任边界。比如你的 Web 服务器和数据库之间,就是一条信任边界。跨过这条边界的流量,必须被严格检查。

我曾经踩过的坑:有一次画 DFD,我把“用户浏览器”和“前端 CDN”画成了同一个外部实体。结果漏掉了 CDN 回源时的身份验证威胁。后来被攻击者利用 CDN 缓存投毒,差点出大事。记住:每一个不同的网络跳转,都可能是一条新的信任边界。

四、实战:画一张登录模块的 DFD

光说不练假把式。我们拿一个最简单的登录模块来画 DFD。假设系统有:浏览器、Nginx、登录服务、用户数据库、Redis 会话缓存。

下面这张 SVG 图,就是典型的 DFD 画法。注意看信任边界的划分:

登录模块 DFD(数据流图) 用户浏览器 Nginx 登录服务 用户 DB Redis 会话 登录请求 转发请求 查询用户信息 写入会话 信任边界:服务端内网

画完这张图,我们就可以用 STRIDE 来分析了:

  1. S(假冒):用户能不能伪造请求头冒充他人?Nginx 和登录服务之间有没有双向认证?
  2. T(篡改):登录请求在传输过程中能不能被中间人篡改?
  3. I(信息泄露):用户 DB 返回的数据有没有包含密码哈希?Redis 里的会话能不能被其他服务读取?
  4. E(权限提升):登录服务有没有可能被利用来执行管理员操作?

你看,一张图 + 一个模型,威胁就变得可枚举、可讨论了。

五、画 DFD 的三个实用原则

画 DFD 不是艺术创作,别搞得太复杂。我总结了三句话:

  • 原则一:只画一层。别试图把每个微服务里的子模块都画出来。先画系统级 DFD,再针对高风险区域画子 DFD。
  • 原则二:标清信任边界。用虚线把不同信任等级的区域圈出来。跨边界的每一条数据流,都是潜在的攻击面。
  • 原则三:数据流必须有名字。别只画箭头,写上“用户登录请求”、“返回用户信息”。这样别人一看就懂。
避坑指南:我曾经见过一个团队,DFD 画了 20 多个过程节点,结果没人能看懂。记住:DFD 是沟通工具,不是毕业设计。画到能让一个刚入职的同事看懂,就够了。

六、威胁建模的输出是什么?

很多人以为威胁建模的输出是一堆报告。其实不是。真正的输出是一份经过排序的威胁清单,以及对应的缓解措施。

我习惯用表格来记录:

威胁编号 STRIDE 类型 威胁描述 影响 缓解措施 优先级
T-001 Spoofing 攻击者伪造 JWT 登录 高 JWT 使用 RS256 签名,并校验 iss/aud P0
T-002 Tampering 登录请求被中间人篡改 高 全链路启用 HTTPS,HSTS 强制 P0
T-003 Info Disclosure 登录接口返回密码强度信息 中 统一错误提示,不暴露具体字段 P1

有了这张表,开发团队就知道先修什么、怎么修。安全需求也就从“我们要做安全”变成了“我们要修 T-001 和 T-002”。

我的习惯:威胁清单一定要和产品经理、开发一起评审。有时候你觉得是 P0 的威胁,业务方觉得可以接受风险。那就记录下来,签字确认。别自己闷头干。