需求阶段威胁建模实战:把安全左移真正落到产品源头 上周我参加一场需求评审会产品经理兴致勃勃地讲完“文档在线分享”的新功能我随口问了一句“分享链接会带上用户身份吗如果链接被人转发出去拿到的第三方能不能直接访问文档”会议室安静了两秒产品经理开始翻需求文档最后来了一句“这个……我们还没想过。”这就是需求阶段威胁建模存在的意义。安全左移这几年在行业内被反复强调但很多人对“左移”的理解停留在“早一点做安全测试”或者“早点接入扫描工具”真正把安全思考推进到需求阶段的团队其实很少。需求阶段做一次威胁建模成本可能只是开一次会但它能把大量“做完再返工”的隐患直接掐灭在源头。这篇文章我就把自己在多个项目里实践需求阶段威胁建模的完整方法、踩过的坑和可直接复用的模板整理出来给正在推动安全左移落地的同学一个参考。1. 为什么要在需求阶段做威胁建模1.1 安全左移的本质是降低修复成本安全左移的核心逻辑其实非常朴素越早发现问题修复成本越低。IBM 的一份经典数据虽然不是绝对精确但它描述的量级关系至今仍被业界广泛引用——如果需求阶段修复一个缺陷的成本是 1设计阶段大概是 20 倍编码阶段 40 倍测试阶段 60 倍发布上线之后可能到 100 倍甚至更多。这个成本曲线背后是真实的工程逻辑。需求阶段的一个安全决策失误影响的不是一个函数的写法而是整个功能的形态。拿“文档分享”来说如果在需求阶段没有明确“分享链接必须绑定访问者身份”这条约束后续的设计会围绕“匿名链接访问密码”来做编码、测试全部跟着这个假设走。等上线后被人抓包或者遍历ID发现漏洞你改的就不只是一行代码而是改需求、改设计、改接口、改前端流程甚至要处理已经泄露的数据。我见过不少项目安全漏洞本身不复杂复杂的是在错误的需求假设上叠加了几层设计之后修复成本被放大了好几倍。所以安全左移不是把安全测试提前一点那么简单它真正应该做的是把“安全需求”当作和功能需求同等重要的一等公民在需求阶段就想清楚这个功能需要防御什么。而威胁建模就是系统化完成这个思考过程最有效的手段。1.2 需求阶段建模与设计阶段建模的分工很多团队一提到威胁建模条件反射想到的是数据流图、STRIDE、攻击树这些设计阶段的东西。需求阶段做的威胁建模跟设计阶段的粒度完全不同两者解决的问题也不一样。设计阶段的威胁建模回答的问题是“这个技术方案安全吗”你需要拿到具体的架构设计画出详细的数据流图标记每个组件、每条数据通路、每个信任边界然后分析攻击者可能从哪里打进来。这个阶段的分析可以直接指导具体的安全方案选型比如是加签名还是加加密是走网关还是走应用层校验。需求阶段的威胁建模回答的问题是“这个业务场景需要考虑哪些安全风险”它不关心具体技术实现只关心业务逻辑、角色权限、数据敏感度、外部交互方式这些“需求层”的信息。举一个例子一个支付相关的业务需求阶段要识别出“账号可能被盗用发起支付”这个风险并把它转化为“必须有身份核验机制”这样的安全需求至于身份核验是上双因素认证还是行为风控那是设计阶段才需要考虑的。这两个阶段是上下游关系需求阶段的输出一份安全需求清单在设计阶段被进一步细化成具体的安全方案。如果跳过需求阶段直接在设计阶段建模很多问题在设计阶段看起来是“方案怎么加固”的问题实际上根源是“需求当初就没想清楚”这时候能做的往往只是打补丁。1.3 方法选型轻量优先威胁建模的框架不少OCTAVE、PASTA、TRIKE、VAST每个都有完整的方法论支撑但我不建议一上来就选重框架。OCTAVE偏向组织级风险评估PASTA强调与业务目标对齐、攻击者视角的分析这些方法论本身没问题只是对需求评审来说太重了——全套跑下来需要几天时间还要专门的培训大多数团队根本坚持不了。我实践下来最顺手的是“场景拆解 简化版数据流图 STRIDE清单 风险排序”的组合。STRIDE伪造、篡改、否认、信息泄露、拒绝服务、权限提升虽然不是为需求阶段量身定做的但它的好处在于每种威胁类型都对应一类明确的安全目标可以直接翻译成安全需求。比如你识别出“信息泄露”威胁对应的安全需求就是“机密性保护”识别出“伪造”威胁对应的安全需求就是“身份认证”。这个映射非常自然即使是没有安全背景的产品经理带着一份STRIDE提问清单也能参与讨论。2. 核心细节解析与实操要点2.1 需求阶段威胁建模需要的五个输入做一次需求阶段的威胁建模不需要等所有需求细节都冻结但要确保五个输入基本齐备否则讨论容易变成空谈。第一个是业务需求描述。至少要有一页纸的需求摘要能把业务场景讲清楚谁在用、用来干什么、核心流程是什么。第二个是角色权限模型系统里有哪些角色每个角色能做什么、不能做什么这决定了信任边界和越权分析的起点。第三个是数据分类清单系统里流动的数据哪些是公开的、哪些是敏感的个人信息、哪些是严格受限的商业数据这个直接决定“信息泄露”类威胁的严重程度。第四个是既有系统架构的简要信息新功能是搭在已有系统上还是全新系统有没有已有的认证、权限、审计基础设施可以复用。第五个是合规要求比如涉及个人信息就先标记出来涉及金融交易的就要考虑强认证和交易日志。这些输入不需要规范的文档一张半成品需求幻灯片、几个人口头对齐一下也可以。关键是别跳过角色和数据分类这两个是我见过被忽略最多、后来出问题最多的点。2.2 STRIDE逐项提问从威胁到需求STRIDE 六个字母对应的威胁类型在需求阶段可以被转化成一组非常接地气的提问清单。不要一上来就念威胁建模理论就拿业务场景一个一个问伪造Spoofing这个场景里需要确认“操作者是谁”吗如果不需要确认身份那意味着任何人都能以任意身份做事这是不是业务能接受的如果需要确认现有的手段登录、API密钥、数字签名够不够篡改Tampering业务数据有没有可能被未经授权地修改修改之后会造成什么后果比如订单金额被改了、日志被改了、配置被改了分别是什么影响否认Repudiation用户做了某个关键操作之后系统有没有能力证明“是他做的”没有不可否认性的话用户投诉、纠纷、审计的时候会不会扯皮信息泄露Information Disclosure数据会不会被不该看到的人看到这个“不该看到的人”不仅是外部攻击者还包括内部越权、合作伙伴滥用、测试环境泄露等。拒绝服务Denial of Service服务不可用会造成什么损失业务上能不能接受有没有对资源消耗失控的担心这里的重点不是搞一套DDoS防御方案而是看这个功能在业务上的可用性优先级。权限提升Elevation of Privilege低权限用户有没有可能做到高权限用户才能做的事普通用户能不能访问管理接口、修改他人数据、执行管理操作每识别出一条威胁就直接标记它对应的安全属性认证、完整性、不可否认性、机密性、可用性、授权。这个映射关系简单直观是需求阶段威胁建模最有生产力的环节——因为每个威胁都能直接变成一个后续可追踪的安全需求条目。2.3 风险排序安全需求也要分优先级需求阶段威胁建模最常见的失控方式是识别出了二十几条威胁然后每条都想做成安全需求最后产品经理直接拒绝配合。安全需求不是多多益善它要跟功能需求抢开发资源必须排序。我在团队里默认用“可能性 x 影响”两维打分每个维度分高、中、低三档得出总的优先级。不引入复杂的CVSS、DREAD评分体系原因很简单需求阶段很多细节还没定打分太精确反而是伪精确。可能性看这个威胁是否容易被触发——是否需要特殊条件、是否需要攻击者具备很高权限或者很多前置知识影响看触发后对业务、客户、资产的实际损失。排序结果直接映射到需求的优先级体系里。最高优先级的高风险且高可能性必须成为本迭代的安全验收条件中风险的进产品backlog在后续迭代按计划消化低风险的记录下来留档每季度复盘一次看业务变化后是否升级。这样安全需求就和普通需求一样进入了迭代排期而不是游离在流程之外的“安全待办清单”。2.4 安全需求怎么写才不像废话需求阶段威胁建模的最终产出是安全需求但它太容易写成废话了。我见过无数条类似“系统应具备良好的安全性防止恶意攻击”这样的描述这种需求没有任何验证手段提了等于没提。能落地的安全需求至少要包含三个要素可验证的行为描述、验证方式、对应当前威胁。行为描述要说清楚系统在什么条件下必须做什么而不是空泛地说“具备某某能力”。举例来说如果识别出“文档分享链接被转发导致越权访问”的信息泄露威胁对应的安全需求不建议写成“分享链接应安全”而是写成“当用户访问分享链接时系统必须校验其登录状态且仅当该用户拥有文档的查看权限时才允许加载内容”。更进一步我喜欢用Gherkin格式把安全需求写成验收条件这样开发、测试、安全三方都清楚什么算“做到了”。功能: 文档分享的越权访问控制 场景: 访问分享链接时校验访问权限 当 未登录用户访问带令牌的分享链接 那么 系统跳转到登录页面 并且 登录后若该用户不在分享名单中 那么 系统返回403且不加载文档内容这种写法的好处在于它直接进入开发验收和测试用例不会变成一份无人问津的安全文档。安全需求跟着用户故事走、跟着测试走才真正在流程里活下来了。3. 实操过程与核心环节实现3.1 会前准备与人员要求需求阶段威胁建模建议开成一次专题会时长控制在90分钟以内太长大家注意力会散产出质量反而不高。参会人员不需要多必须到的是产品经理讲清楚业务需求、技术负责人了解系统边界和约束、测试负责人在验收条件上把关。如果团队里有安全工程师或者有安全经验的老研发负责引导讨论和记录结果没有的话也不用等让技术负责人拿着检查清单引导也行。会前必须给参会人发一份一页纸的会议材料内容包括本次要分析的功能简介、参与的角色列表、涉及的数据类型、一个新功能最小可用的系统边界图。这个材料不需要写得多工整重点是让所有人到会之前脑子里有一个确定的讨论对象而不是现场开始同步需求背景——那会浪费大量时间。会议最大的一坑是“什么需求都往里塞”。威胁建模会非常容易跑偏成功能评审会、技术方案讨论会。在会议开始前就要明确不讨论功能要不要做、不讨论技术怎么实现只回答一个问题——这个场景存在哪些安全风险哪些必须转化为需求。3.2 标准流程六步走我在实际项目中把流程固定成六个步骤跑顺之后基本不会出大错。第一步业务场景拆解。让产品经理把主要业务场景讲一遍最好拆成“某人通过某方式完成某件事”这样的句式。拆出三到五个核心场景就够了不要追求穷举所有边角场景。第二步画简版数据流图。在白板上画出主体、数据、处理过程和存储这个阶段不需要高大上的建模工具方框和箭头足够了。画图的核心目的不是画得漂亮而是让全体参会者对齐信息流转路径——很多越权问题的根源就是对数据路径理解不一致。第三步标记信任边界。在图上标出“线上用户不可信”“内部服务之间可信”“数据库边界可信”这些边界线。信任边界标错了后面所有分析都会错。有个很常见的错误是默认“内部系统互相调用可以信任”实际上内部接口被任意调用导致越权的案例多了去了。第四步用STRIDE逐项过。按照伪造、篡改、否认、信息泄露、拒绝服务、权限提升的顺序逐个场景提问每识别出一个威胁就记录一条。这一步最考验引导者的节奏不要在一个威胁上无限深挖先保证六类都过一遍。第五步风险登记和排序。把识别出的威胁填入风险登记表用可能性x影响算法快速排序分类到高、中、低三档。第六步把高、中优先级威胁转化为带验收条件的安全需求写进需求文档或用户故事指定负责人。3.3 完整示例在线文档分享功能我用“在线文档分享”这个例子走一遍完整流程方便大家直接参考。业务场景拆解后得到三个核心场景用户A将文档主动分享给用户B用户A生成一个分享链接任何人获得链接即视为被授权用户A取消分享后链接失效。这个拆解本身就能发现业务逻辑上的风险点——第二个场景中“获得链接即视为被授权”这就是一个需要重点审视的需求假设。画简版DFD文档所有者、Web应用、文档存储服务、访客两条主要数据流分别是“所有者上传并设置分享权限”和“访客通过链接拉取文档”信任边界画在Web应用对外一侧存储服务与Web应用之间视为内部边界。STRIDE逐项过一遍后识别出以下核心威胁威胁类型威胁描述可能性影响优先级信息泄露分享链接被转发给未授权人员对方可以直接访问文档高高高伪造访客伪造所有者身份获取更高权限中高高篡改文档内容被未授权访客修改如果支持在线编辑中高中否认所有者否认发起了分享导致纠纷时定责困难低中中权限提升普通访客通过修改链接参数访问管理接口中高高针对高优先级威胁直接生成安全需求并写清楚验收条件。比如“分享链接必须绑定访问者身份链接本身不构成授权凭证”这条需求它的验收条件就是未登录用户访问分享链接时系统必须跳转登录已登录但不在文档分享名单中的用户系统返回403且不加载文档内容文档所有者在分享管理页面取消分享后所有已有链接在1分钟内全部失效。值得特别说的是“链接不再作为授权凭证”这个需求它本质上是从业务逻辑层面消除了一整类威胁。如果设计阶段才意识到这一点几乎意味着推翻原有方案而在需求阶段改只是改一个产品规则。这就是安全左移在需求阶段最直观的收益。3.4 工具选型参考从白板到平台化工具层面我的建议是分阶段选型。团队刚刚起步的时候白板、Miro线上白板配一套模板就够了重点是培养威胁建模的思维习惯和团队默契。工具越复杂门槛越高团队反而越不愿意用。等团队跑顺了流程、画DFD有稳定需求之后可以引入微软的Threat Modeling Tool或者OWASP的Threat Dragon。前者是桌面软件免费内置STRIDE分析能根据DFD自动生成威胁清单适合Windows环境下的快速建模后者开源、跨平台存成JSON方便版本管理更适合研发团队通过代码仓库管理威胁模型。再往上走像IriusRisk这类商业平台支持风险库、需求追踪、与Jira对接适合在几十个团队的大规模组织里统一管理威胁建模资产。但我不建议在地基没打好的时候直接上这类平台工具永远只是手段如果团队没有威胁建模的思考习惯和一套稳定的流程工具只会成为第二个没人维护的文档仓库。最终的工具决策可以用一个简单标准判断这个工具是否让“识别一个威胁、记录一个风险、追踪一条需求”变得更顺畅。工具带来的额外开销如果超过了识别威胁本身的开销那就是选错了。4. 常见问题与排查技巧实录4.1 团队没有安全人员怎么办没有专职安全人员是绝大多数团队要面对的现实但这不意味着需求阶段威胁建模就做不了。我见过不少团队第一次做威胁建模的时候完全由产品经理和技术负责人主导安全背景反而是通过几次讨论一点点建立起来的。做法是把威胁建模开成“教练式”的会前两次由有经验的人外部顾问、研发团队里安全技术比较好的老员工带着做STRIDE清单提前发给所有人会上引导产品经理自己回答“如果链接被转发会怎样”这类问题。几次下来产品经理自己就会养成在需求描述中补充安全约束的习惯。我在实操中发现产品经理绝对能理解威胁建模的逻辑前提是你不要用安全术语把他劝退。你用“什么情况下坏人能拿到不该拿的东西”来提问比“评估Spoofing威胁的暴露面”效果好十倍。另外没有专职安全人员的团队更应该建立一份业务侧的常见威胁检查清单——比如所有上传功能都检查一次文件类型校验所有分享功能都检查一次越权访问。这份清单可以来自团队经验、公开的行业清单、或者第一次威胁建模的会议记录它能保证在没有专家的情况下团队也能覆盖掉最常见的坑。4.2 敏捷迭代太快建模跟不上怎么办敏捷团队最常见的抱怨是威胁建模太慢了一个迭代就两周哪有时间专门开一次会。我的处理方式是分层重大版本、新模块引入、涉及资金和敏感数据的功能变更做一次完整的威胁建模小的迭代增量走一个15分钟的快速增量检查。快速增量检查其实不复杂把这次变更涉及的数据流和上一次威胁建模时的DFD对比一下问问“这次有没有新增数据入口、有没有新增信任边界、有没有改变数据流向”。三个问题都回答“否”那这次变更就不需要重新建模。只要回答有一个“是”那就要对新增部分快速过一遍STRIDE。这个方法跑顺之后完整建模的需求频率会很低——可能一个季度只有几次而每次增量检查只需要15分钟。威胁建模才不会被团队当成流程负担而是真正成为迭代的一部分。还有一个实践技巧把威胁建模结果转化为安全用户故事放进backlog之后研发团队消化安全故事和消化功能故事的节奏是相同的。不要试图在同一个迭代里既让开发写代码又处理一堆紧急安全需求除非这个威胁的优先级确实高到必须立刻修。4.3 安全需求后面没人落实怎么办需求阶段识别出了风险、写好了需求结果开发迭代过程中还是被当作“软需求”晾在一边——这是很常见的情况。问题的根源往往不在执行端而是安全需求没有跟验证活动绑定起来。我在实践中的做法是每条安全需求都要绑定至少一个验证动作并且把验证动作写进测试计划。比如前面提到的“分享链接必须绑定访问者身份”这条需求对应的验证动作是一个集成测试用例专门覆盖“已登录但未授权用户访问分享链接返回403”的场景。测试用例挂在需求ID下面需求没有闭环测试就有一项是红的。另外一个“隐形”的原因是安全需求在需求文档里单独开了一个章节而不是写在每个用户故事里。产品经理评审需求的时候只看到功能描述看不到安全条件开发拿到的用户故事里也没有。安全需求必须内嵌到相应的用户故事中和功能条件一起被开发、测试共同审阅。我在团队里定的规矩是一条用户故事如果带安全验收条件必须以安全验收条件全部通过作为完成定义的一部分否则这个故事不能算“完成”。4.4 常见翻车场景与避坑做得久了会发现需求阶段威胁建模的翻车场景高度重复我总结几个最常见的。翻车一把DFD当艺术创作。有些团队把大量精力花在画精细的数据流图上恨不得把每个字段的流转路径都画出来结果STRIDE分析只花了15分钟。这是典型的倒置。需求阶段的数据流图只需要到实体和存储级别画图的目的不是图本身而是用它来对齐讨论对象、定位边界。翻车二风险登记表成了“死亡台账”。识别出几十条威胁开会时大家斗志昂扬会后表格一存再也没有人打开过。要避免这个问题核心是把高优先级的威胁转化成需求动作而不是“风险记录”。“风险记录”给人感觉是可以暂缓而“需求条目”是需要排期的。翻车三威胁清单不随需求演化。需求阶段做完建模后续需求每次都变化威胁模型还停留在三个月前的版本。威胁建模不是一次性的至少在功能发生实质性变化的时候要回看一次。我在实践中每两周在迭代计划会之前花10分钟翻一下已有需求列表看有没有需求变化触发了重新建模的条件。翻车四把威胁建模等同于“安全加固会议”。团队一旦发现安全痛点就开始讨论“要不要上WAF”“要不要做加密”这又跑到了设计阶段。需求阶段的核心产出是“要什么”不是“怎么要”。“要不要在分享功能中引入访问者身份校验”是需求问题“用JWT还是OAuth实现校验”是设计问题两者分开讨论效率才高。4.5 一轮摸爬滚打后的自查清单如果你准备在团队里推行需求阶段威胁建模建议先对照下面这张清单自检把节奏先理顺再谈产出。检查项是否做到有固定的迭代周期触发威胁建模而不是想起来才做产品经理能清晰识别出涉及的敏感数据类型和角色权限每次需求评审都有STRIDE清单在手不会遗漏威胁类型识别出的威胁经过可能性x影响排序形成优先级高优先级的威胁被写成带验收条件的安全需求进入迭代排期安全需求由开发、测试在完成定义中确认闭环需求变更后能及时复盘已有威胁模型增量更新如果七项里面有超过两项打不了勾说明威胁建模还没有真正融入研发流程先补最短板的一项比全面铺开更有用。最后分享一个尝试了很久才沉淀下来的习惯带过几次需求阶段威胁建模之后我最大的体会不是“方法有多复杂”而是“坚持做简单的事效果反而最好”。一开始我们每个功能都试图把威胁识别做得很全团队成员疲惫不说产出质量也一般。后面我们做了一个调整每次建模结束后把这次识别出的威胁和对应的安全需求整理进一个团队共用的“安全需求库”按业务类型分类。这个库前期看起来平平无奇但坚持两三个迭代之后效果会非常明显——新项目做威胁建模时产品经理可以直接从库里的同类业务调出历史安全需求做对照替换掉一半从零开始思考的时间。威胁建模真正沉淀成了团队的资产而不是每次从零起步的会议。如果你所在团队正准备开始安全左移的实践我建议把这件事当成一个长期的建设工程来做每一轮威胁建模都是在为团队积累一份能不断复用、持续演化的安全需求知识库。