2. 安全需求分析:威胁建模方法(STRIDE)、安全需求导出、安全用例编写

好,咱们进入第二章。上一章聊了V模型和安全的关系,说白了就是「安全不能是事后补丁」。那怎么在项目一开始就把安全想清楚?靠拍脑袋肯定不行。

我个人习惯,在需求分析阶段必须做一件事——威胁建模。不做威胁建模,你根本不知道系统会挨什么打。

2.1 威胁建模:先当黑客,再当工程师

威胁建模是什么?简单说,就是站在攻击者的角度,把系统从头到尾「黑」一遍。在纸上黑,在脑子里黑,用结构化方法黑。

我见过太多团队,上来就写代码,写到一半发现「哎呀这个接口没鉴权」。嗯,那时候改起来就痛苦了。威胁建模就是帮你提前发现这些坑。

2.1.1 STRIDE:微软给的六顶思考帽

STRIDE 是微软提出的一套威胁分类方法。六个字母,代表六类威胁。我每次做威胁建模,都会拿这张表一个一个过。

威胁类型 英文 定义 举个栗子
S 欺骗 Spoofing 冒充他人身份 伪造用户Token登录
T 篡改 Tampering 非法修改数据或代码 中间人改请求参数
R 抵赖 Repudiation 否认做过某操作 用户说「我没下单」
I 信息泄露 Information Disclosure 敏感数据被未授权访问 数据库明文存密码
D 拒绝服务 Denial of Service 系统资源被耗尽 刷验证码接口导致服务挂掉
E 权限提升 Elevation of Privilege 普通用户获得管理员权限 越权访问后台接口

你想想看,这六类几乎覆盖了所有常见的攻击面。我在项目中遇到过最典型的案例——一个物联网设备管理平台,开发团队只做了登录校验,没做接口级权限校验。结果普通用户直接调用管理员接口,把所有设备固件都升级了。这就是典型的 E(权限提升) 问题。

我的小技巧: 每次过STRIDE,我都拿不同颜色的笔在架构图上标。红色标S,蓝色标T……最后看哪个颜色最多,哪个方向就是最需要投入的。

2.1.2 数据流图:画出来,才能看清楚

做威胁建模之前,必须先画数据流图(DFD)。没有DFD,威胁建模就是空中楼阁。

DFD 要画清楚:

  • 外部实体:用户、第三方系统
  • 处理过程:业务逻辑、API服务
  • 数据存储:数据库、缓存、文件
  • 数据流:请求、响应、消息

画完DFD,在每个数据流上问自己:这个流会不会被S?会不会被T?会不会被I?

核心原则: 每个数据流至少匹配一个STRIDE威胁。如果某个流你找不到威胁,说明你没想透,或者这个流根本不需要存在。

STRIDE 威胁建模流程 1. 画数据流图 识别实体/过程/存储 2. 逐流过STRIDE S/T/R/I/D/E 六类 3. 记录威胁清单 编号/类型/影响/风险 4. 导出安全需求 威胁 → 需求转化 5. 编写安全用例 正常/异常/攻击场景 6. 团队评审 架构师+安全+开发 迭代优化 💡 说明: 威胁建模不是一次性的。每次架构变更、每次新增接口,都要重新走一遍这个流程。

2.2 安全需求导出:从威胁到需求

威胁清单有了,下一步就是把它变成可落地的安全需求。这一步很多人做不好——要么写得太虚(「系统要安全」),要么写得太技术(「用AES-256加密」)。

我建议用这个模板来写安全需求:

安全需求模板:

作为 [角色],当 [场景] 时,系统应 [安全措施],以防止 [威胁类型]。

举个例子:

  • 威胁:攻击者伪造用户Token登录(Spoofing)
  • 安全需求:作为登录服务,当用户发起认证请求时,系统应校验Token的签名和有效期,以防止身份欺骗。

你看,这样写出来,开发知道要做什么,测试知道要测什么,安全也知道要审什么。

2.2.1 需求优先级:别想一口吃成胖子

威胁可能有一百个,但资源有限。怎么排优先级?我个人习惯用 DREAD 模型来打分:

维度 说明 评分(1-10)
D 潜在损失 如果被利用,损失多大? 数据泄露=10,服务降级=3
R 可重现性 攻击者能稳定复现吗? 每次都能=10,条件苛刻=2
E 利用难度 攻击门槛高不高? 有现成工具=10,需要0day=2
A 受影响用户 影响范围多大? 所有用户=10,单个用户=3
D 可发现性 攻击者容易发现这个漏洞吗? 公开接口=10,内网接口=3

总分越高,越要优先处理。我曾经在一个项目中,有个威胁DREAD总分高达48(满分50),但团队觉得「概率低」想推迟。我坚持要求必须当期修复——结果上线第三天就被白帽子打穿了。嗯,从那以后,我再也不信「概率低」这种话了。

注意: 安全需求不能只写在文档里。必须进入需求管理系统(Jira、Polarion等),和功能需求一样有优先级、有负责人、有验收标准。

2.3 安全用例编写:把需求变成可执行的剧本

安全需求写好了,但开发不一定知道怎么测。这时候就需要安全用例。

安全用例和普通用例的区别在哪?普通用例描述「正常流程」,安全用例描述「攻击流程」和「防御验证」。

2.3.1 安全用例三要素

我一般把安全用例分成三个场景:

  1. 正常场景:合法用户按规则操作,系统正确响应。
  2. 异常场景:用户操作不规范(如输入超长字符串),系统优雅处理。
  3. 攻击场景:用户故意尝试绕过安全机制,系统成功拦截。

举个例子,针对「登录接口防暴力破解」这个安全需求:

用例ID 场景类型 前置条件 操作步骤 预期结果
UC-SEC-001 正常场景 用户已注册 输入正确账号密码,点击登录 登录成功,返回Token
UC-SEC-002 异常场景 用户已注册 输入错误密码5次 第5次后账号被临时锁定15分钟
UC-SEC-003 攻击场景 攻击者无合法凭证 用自动化脚本每秒尝试100次不同密码 系统触发频率限制,返回429状态码
我的经验: 攻击场景的用例最难写,因为你要「像黑客一样思考」。我每次写攻击用例前,都会先搜一下这个功能有没有现成的CVE或公开漏洞报告——站在巨人的肩膀上,比自己瞎想靠谱得多。

2.3.2 安全用例的验收标准

安全用例写完了,怎么算「通过」?我定三个标准:

  • 功能正确:正常场景能走通,不影响用户体验。
  • 防御有效:攻击场景被拦截,系统没有泄露敏感信息。
  • 日志完整:所有安全事件都有审计日志,能追溯到谁、什么时间、做了什么。

这三个标准缺一不可。我见过一个团队,安全用例全过了,但上线后发现日志没打——出了事根本查不了。你说这安全用例算过了吗?

2.4 本章小结

来,咱们捋一下这章的核心:

  • 威胁建模:用STRIDE六类威胁,对着数据流图一个一个过。
  • 安全需求导出:用「角色+场景+措施+威胁」模板,把威胁变成可落地的需求。
  • 安全用例编写:分正常、异常、攻击三个场景,把需求变成可执行的测试剧本。