news 2026/10/21 16:26:10

需求阶段威胁建模实战:安全左移怎么落地才不走过场

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
需求阶段威胁建模实战:安全左移怎么落地才不走过场

我见过太多开发团队把安全测试当成上线前的压轴戏:提测之后扫描器跑一轮,漏洞列表甩过来,开发打开一看,全是需求阶段没想清楚的设计缺陷。这种事后补漏的滋味,谁做谁知道。所以这几年“安全左移”被反复提起,但它不该只是口号,落到最前端,是一个非常具体的动作——需求阶段做威胁建模。这篇文章就把这件事的完整思路、实操步骤和踩坑记录一次性盘清楚。如果你正打算在团队里推动安全左移,或者刚被叫去牵头搞威胁建模,这篇文章应该能帮你少走不少弯路。

1. 为什么这笔账算到最后,需求阶段的威胁建模最划算

1.1 安全左移不是新概念,为什么大家还是做不到

“安全左移”这四个字,绝大多数人都认同,但能真正做到的团队不多。我见过不少团队号称在做安全左移,实际动作只是请安全工程师提前参加了一次评审会,平时依然各干各的。原因不在意愿,而在于安全工程师在需求阶段根本没有可以落手的抓手。

开发阶段有代码,测试阶段有系统,安全工程师可以做代码审计、可以做渗透测试、可以跑扫描器。需求阶段有什么?只有一份PRD或者用户故事,上面写满了业务流程,没有一行是安全属性。很多安全工程师面对这种材料,第一反应是不知道从哪儿问起,产品经理也不知道该怎么回答。于是需求评审变成了“安全确认:无异议”,威胁建模也就沦为走过场。

要让安全左移真正生效,第一步就是在需求阶段建立一套所有人都能用的分析语言。威胁建模恰恰就是这套语言:它不要求你立刻发现漏洞,而是要求你顺着需求把系统内外的角色、数据和信任关系捋一遍,再针对性地问“如果这里被恶意利用会怎样”。做完这一步,安全需求就会自然浮现出来,不需要谁拍脑袋。

1.2 修复成本曲线:需求阶段改一个决定,能省下多少返工

先聊一个多数人都听过但很少认真算过的数字。行业里普遍接受一条缺陷修复成本曲线:需求阶段修复一个缺陷的成本系数大约是1,编码阶段大约是10,测试阶段大约是20到50,上线之后可能是100甚至更高。不同团队的具体数字会有差异,但量级基本不会错。

为什么跨度这么大?因为阶段越靠后,修改一个决定要牵动的东西越多。举个支付类项目的例子,需求里只写了“用户可以通过手机找回密码”。在需求阶段如果多问一句“手机号要不要验证、验证码能不能重试”,修改成本仅仅是改几行文字描述。可如果系统已经上线才发现找回密码逻辑允许攻击者无限重试验证码,要改的不只是页面逻辑,还有后端的频率限制、操作日志、风控规则、客服申诉流程,甚至要考虑在途的恶意请求怎么追溯。一次改动的成本,差了不止一个量级。

发现阶段相对修复成本以找回密码需求为例
需求阶段约1改一句验证码规则描述
编码阶段约10改接口加频率限制,重新联调
测试阶段约20到50改完还要补回归测试用例
上线后100甚至更高数据修复加灰度加客服,联动全局

所以需求阶段做威胁建模,本质上是用一轮头脑风暴,去买断后面可能出现的返工。它不是“额外增加工作量”,而是把本来就要花的修复成本,提前挪到最便宜的时间窗口里花掉。理解这一点,你就明白为什么越是复杂的业务系统,越值得在这个阶段多花半小时到一小时。

1.3 需求阶段的威胁建模产出物,不止是一张威胁清单

很多人以为威胁建模的产出物就是一张“威胁列表加修复建议”。实际跑过一次之后你会发现,更值钱的产出物是三个:首先是安全需求条目,这是要写回用户故事卡的;其次是风险决策记录,哪些威胁本次接受、哪些必须修,理由是什么,都要留底;最后是待确认问题清单,需求描述里讲不明白、需要产品方补充澄清的点,也要记下来后面去问。

这三个产出物让威胁建模从“一次讨论”变成“一份基线”。下次同一个模块有需求变更时,直接翻上次的记录就能知道哪些点动过、哪些风险已经被接受。没有这份基线,每次建模都要从头再来,团队很快就会疲倦。

2. 建模之前先看懂需求:角色、数据、信任边界三个输入

威胁建模不是凭空想象。它的原材料就是需求文档里被当成常识忽略掉的信息。我习惯把输入收敛成三个问题:谁在用这个功能?功能经手了哪些数据?哪些环节是外部不可信的?这三个问题覆盖了大多数需求,也是下面整条分析链的地基。

2.1 谁在用:别把“用户”当成一个角色

第一次做需求阶段威胁建模时,最常见的错误是把“用户”当成单一角色。实际上,一个真实系统里的角色至少可以拆成:未登录用户、普通登录用户、管理员、客服、第三方系统。每个角色能碰到的数据和操作都不一样,威胁自然也不一样。

以“用户找回密码”为例,普通用户能发起重置请求,管理员可能能看到重置记录,客服在协助用户时可能需要临时查看验证信息,第三方短信网关直接触达用户手机。如果只写一个“用户”,你就永远不会去问“客服能不能帮用户重置密码”“重置密码的操作是否要留痕”。角色列表一旦写不完整,后面设计权限模型时一定会出问题。

所以建模会上,哪怕需求文档只字未提角色列表,也要先花五分钟把角色写出来,包括“系统它自己”也算一个角色。写不出来的部分,恰恰是需求最模糊的部分,也是最容易出现越权漏洞的部分。

2.2 经手哪些数据:敏感字段的边界在哪里

第二个问题是数据。这里说的不只是“手机号是敏感数据”这种常识,而是要具体到:这个需求从哪个环节开始收集数据,数据存在哪里,要传给谁,谁有权看到,日志里会不会记录。

拿找回密码举例子,这个需求经手的数据至少有:手机号、验证码、重置后的新密码、操作记录、日志。其中验证码是最容易出问题的:很多团队只在传输时做了加密,却忘了日志里明文打印验证码,于是攻击者拿到日志就能直接重置任意账号。

在需求阶段,这类问题特别好拦下来。你只需要在数据列出来之后,逐项问一句“这条数据如果泄露,后果是什么”。不需要懂密码学,也不需要懂扫描器,只需要顺着业务流程走一遍。这一步做扎实了,后面设计数据脱敏和日志规范就有明确依据,而不是安全部门拍一个通用要求让开发去猜。

2.3 信任边界:系统内部和外部世界在哪儿分界

信任边界这个概念听起来玄,其实就是问一个问题:从哪个点开始,经过的数据不再受当前系统控制。用户手机上的App是不受控制的终端,短信网关是外部系统,第三方登录服务也是外部系统。凡是跨过这些边界的数据,都必须默认不可信。

还以找回密码为例,手机短信验证码从短信网关返回,再到用户输入,整条链路跨越了至少三条信任边界。如果开发在某个接口里认为“既然验证码是我发的,回传时就不用太严格”,那就是在信任边界上埋雷。常见的处理方式是:验证码要带一次性属性,要和会话绑定,要限时生效,重试次数要封顶。这些不是安全工程师的个人偏好,而是信任边界两端的必然要求。

需求阶段如果能把信任边界画出来,产品经理和开发就很容易达成共识:边界两侧的所有输入都要验证。这份共识,比任何一份安全规范文档都管用,因为它长在具体需求上,不会被人当作空泛的合规条款。

2.4 隐式步骤:需求文字里最容易漏掉的威胁角落

还有一个实操习惯:做任何需求威胁建模之前,先把需求文字里没有写、但业务流程中必须存在的“隐式步骤”补出来。找回密码这个故事,字面上只有“输入手机号、收验证码、设新密码”三步,但真实流程还隐含着“系统发送验证码”“验证码校验”“失败计数”“触发锁定”“发送提醒通知”。如果建模时只对着表面步骤分析,很多威胁就会藏在隐式步骤里。

隐式步骤往往是攻击者最喜欢下手的地方。比如“失败计数”如果没人提到,开发可能就不会实现锁定策略,验证码爆破就成了必然结果。你可以在建模会上专门留出一段时间,让产品讲一遍“这个单子背后,系统还要替用户做哪些事”,把每一个隐含动作都补进数据流图里再分析。

3. 从需求描述到威胁清单:一条可复制的五步流程

有了三个输入之后,就可以开始建模了。我常用的流程一共五步,可以在一次一小时的建模会上全部完成。以下每一步都配找回密码的例子,方便对照复现。

3.1 把需求翻译成数据流图,越简单越好

第一步是画数据流。不需要标准软件工程里那种复杂的DFD符号,白板上画几个圆几个箭头就行:用户、前端页面、后端服务、数据库、短信网关,谁向谁请求什么数据,画清楚即可。

有人会问,需求阶段连接口都没定,画什么数据流?我的经验是,越没确定细节,越适合画粗粒度流程。你要的不是精确到字段的时序图,而是确认数据“从哪进、在哪处理、落哪存储、往哪流出”。画完图之后,多数模糊需求会立刻暴露:比如需求里写了“支持手机验证码”,但没说验证码调用的短信网关从哪来,这就值得追问。

3.2 用威胁分类逐项过筛

第二步是用威胁分类法过一遍。这里最常用的是STRIDE,把威胁分成六类:伪装、篡改、抵赖、信息泄露、拒绝服务、权限提升。我不推荐一上来就背全称,直接记中文语义就够了。

威胁分类中文理解找回密码示例
伪装(Spoofing)冒充别人发起请求攻击者冒充用户重置密码
篡改(Tampering)数据被非法修改重置过程中的数据包被改写
抵赖(Repudiation)用户否认做过操作用户否认发起过重置请求
信息泄露(Information Disclosure)敏感数据被不该看到的人看到日志明文打印验证码
拒绝服务(Denial of Service)系统资源被恶意耗尽短信验证接口被刷爆
权限提升(Elevation of Privilege)低权限拿到高权限重置逻辑被用来操作管理员账号

对照数据流图,逐个节点问:

  • 有没有可能冒充别人发起请求?
  • 数据在传输或者存储过程中能不能被改?
  • 用户做完敏感操作后,是否无法证明他做过?
  • 数据会不会被不该看到的人看到?
  • 请求能否把系统打挂?
  • 低权限用户能否干高权限的事?

六类过完,一个需求的威胁面基本上就完整了,后面的修复方向也自然指向对应的节点。

3.3 按影响和可能性排优先级

第三步不是把威胁全都列为必修,而是排序。我给团队用的简化方法是两个维度:影响程度高、中、低,发生可能性高、中、低。九宫格里只有“高影响加高可能”和“高影响加中可能”需要立即处理,其他可以先记录,后面再说。

需求阶段没必要上CVSS那种精细评分,因为此时很多细节还没定。粗粒度排序的好处是,大家不用为了一个不存在的补丁去争论“严重性到底是不是8.5”。排序的结论最好当场定下来,负责人也当场指定,不要拿回会后邮件里讨论。一旦出了会议室,优先级讨论就很容易不了了之。

3.4 把威胁变成可验收的安全需求条目

第四步把选中的威胁转成安全需求条目。安全需求条目必须写清楚条件和预期结果,要能做到验收。格式可以统一为“当……时,系统必须……,以防范……风险”。

比如:“当用户请求发送短信验证码时,系统必须要求先完成图形验证码,并通过频率限制(同一手机号每分钟不超过1次、每天不超过5次),以防范短信轰炸风险。”这句话开发能懂,测试能验证,产品能接受。相比之下,写“注意短信安全”这种话等于没写。

顺带提醒一下,写安全需求条目时,条件、动作、目的三个要素缺一不可。条件决定触发点,动作决定实现逻辑,目的决定为什么存在。有了目的,将来做需求变更时,团队才能判断这条限制能不能放宽。纯堆砌指标的条目,一旦和业务冲突,第一个被砍的就是它。

3.5 回写到用户故事,让开发看一眼就知道安全要求

最后一步是把安全需求写回用户故事。很多团队在建模会上讨论得热火朝天,散会之后威胁清单躺在Wiki里没人再看。要避免这个结果,最好从一开始就把安全验收条件写进故事卡的“验收标准”部分。

用故事卡的语言表达就是:“作为注册用户,我希望通过短信验证码找回密码,以便在我忘记密码时恢复登录;同时验证码仅5分钟内有效,最多可尝试5次,连续失败后该手机关联账号将锁定10分钟。”这样开发看到的不是安全部门外来的要求,而是需求本身的一部分。这一步做不做,直接决定了威胁建模能不能真正改变开发结果。

4. 实测最常翻车的四个场景,每个我都踩过

流程写出来很简单,真正落地的时候问题非常多。下面这几个翻车场景,是过去几年我和不同团队协作时反复遇到的,提前知道能帮你省下不少会议时间。

4.1 翻车场景一:威胁清单变成了合规填空题,没人聊业务

最常见的问题是,建模会开着开着变成了填表大会。安全工程师准备了一份模板,上面列了二十种威胁,大家照着勾选:SQL注入勾上,跨站脚本勾上,越权勾上,完事。会后一问,数据流向哪儿、验证码存在哪里,没人说得清。

这种威胁清单对业务没有意义,因为它是通用项,不是针对这个需求的分析。要破这个局,建模会上应该少看模板,多看那张数据流图。如果大家能围绕图里某一个箭头争论起来,说明建模进入了正题。我甚至建议,会议前五分钟先禁止碰模板,专门把数据流画完再进入威胁分类。你还可以在会议开始时立一个规则:每人发言必须引用具体角色或具体数据流节点,禁止说“可能不安全”这种空话。这个规则听起来机械,但能有效防止会议滑向空对空的讨论。

4.2 翻车场景二:工具带着团队跑,业务问题反而没人问

有些团队买了威胁建模工具,期望导入需求描述后自动输出威胁清单。工具确实能生成候选列表,但它无法理解你的业务。比如工具能提示“接口缺乏身份验证”,可它不知道这个接口面向的是内部管理后台还是公开注册页面,这决定了威胁的严重程度和修法。

我的建议是,把工具当成题库,别当成裁判。威胁建模的核心是对具体需求的分析,而不是从工具的结果里挑选项。自动化可以用于建模之后的持续跟踪,但不能在需求阶段取代人的判断。工具能帮我们把威胁分类枚举得更全,却永远代替不了那个“这段流程如果被打会怎样”的业务直觉。

4.3 翻车场景三:所有威胁都排成高危,等于没有优先级

另一种常见画面是,会上大家为了保险起见,把几乎所有威胁都标成“高影响”,理由是“万一出事谁负责”。结果就是安全团队拿着二十条高危威胁去压排期,开发的反应是免疫,反正每条都是高危,那就都不紧急。

排优先级不是做安全检测报告,而是做风险管理决策。高影响的威胁如果可能性极低,在资源有限时可以先接受并记录,后续再评估。我在会上常常要主动说一句:“这条我们可以放到观察清单,不代表不处理,只是本周不为它排期。”敢于画重点,建模才有实际效果。低危威胁不是被忽略,而是被清楚地记录在决策档案里。观察清单不是垃圾桶,每一条都要写清楚接受风险的理由和重估触发条件,否则它就成了一个免责口袋。

4.4 翻车场景四:会议产出没有回写故事卡,散会即遗忘

这是最可惜的一种翻车。建模会开得不错,威胁识别准确,安全需求也写出来了,但团队下一步排期时,发现故事卡里没有一个字提到安全。原因是会议产出只停留在单独的安全需求清单,没有同步进迭代的管理工具,也没有绑定负责人。

要避免这个坑,至少做两件事:第一,给每条安全需求指定一个明确的交办对象,不写“团队负责”;第二,确认它进入了迭代积压列表,并在验收标准里注明关联的故事卡编号。没有这两步,威胁建模就只能算一次成本,产生不了收益。事后大家还会得出一个错误结论:威胁建模没用。其实不是方法没用,是流程断在那里了。

5. 让需求阶段威胁建模稳定运行的协作机制

流程和避坑都聊完了,最后说说怎么让这件事在团队里持续运转起来。威胁建模不是一次性活动,它需要靠协作机制固定下来,否则永远是某一次领导推动后就没下文。

5.1 谁该坐在建模会上:控制在六人以内

需求阶段的威胁建模会,参会人不用很多,但角色必须覆盖:产品经理、开发的架构或后端负责人、前端负责人(如果涉及前后端交互)、安全工程师、测试工程师。如果需求改动涉及外部第三方系统,再把对接方拉进来。

人数超过六个,会议的节奏和效率会明显下降,很容易变成各说各话。我一般建议采用“核心三人组加按需扩展”的方式:产品、开发、安全必须到,测试和前端在涉及界面或验证环节时再参与。宁可多开半小时小会,也不要开两小时大会。多人大会容易让最会表达的开发主导讨论,反而是最了解业务流程的同事可能没机会开口。另外,建议建模会设一个明确的时间盒,不要超过90分钟。需求阶段的威胁建模追求的是覆盖主要威胁面,不是穷举所有攻击路径。时间一到,把未完成项列入待确认问题清单,比拖堂更有效。

5.2 建模的时机:赶在需求评审之前,别等需求冻结

很多团队的威胁建模放在需求评审之后、开发开始之前,这时候需求已经接近冻结,讨论空间变小了。更好用的节奏是:需求刚有雏形时先做一轮轻量威胁建模,把高风险点暴露出来,产品在评审前就能把安全要求带进PRD。需求冻结后如果还有重大变更,再做一轮增量分析。

我见过一个配合得比较顺的团队,他们的产品每次组织需求评审前,都会在内部先和开发、安全花半小时过一遍数据流图。这半小时让评审会的效率高了很多,因为大家讨论的已经不是“这个方案行不行”,而是更具体的安全设计取舍。需求阶段的威胁建模不是一次性大动作,而是跟随需求演进的轻交互。

5.3 记录工具和模板:能进Wiki就行,别让工具成为门槛

工具不是门槛,记录才是。最简单的做法是,在Wiki里维护一张威胁建模记录表,字段包括:需求编号、需求描述、相关角色、数据与信任边界、威胁清单、优先级、安全需求条目、关联故事卡编号、状态、负责人、备注。

有人问要不要引入专门的威胁建模软件。我的建议是,如果团队规模不大,先用在线白板加Wiki完全够用;等流程稳定了,再考虑用自动化工具辅助管理。引入工具的核心目的是让结果可追踪,而不是为了显得专业。工具越重,团队越容易推迟落地,反而丢掉了“先跑起来再优化”的节奏感。

5.4 度量什么才不跑偏:盯安全需求落地率,而不是威胁发现数量

最后聊度量。千万不要用“一次建模会识别了多少条威胁”作为指标,因为它会鼓励大家把建模会变成凑数大会。真正值得盯的是两个指标:安全需求落地率和设计变更率。

安全需求落地率,统计进入故事卡并完成开发验证的安全需求占全部安全需求的比例;设计变更率,统计需求冻结后因为安全原因发生的设计变更次数。这两个指标一个看“有没有落地”,一个看“是不是及时发现”。它们不会给人制造虚假的安全感,只会让团队逐步意识到,威胁建模减少的是上线后被迫返工,而不是减少了工作量。指标的意义是引导行为,不是被衡量本身绑架。

我自己的体会是,需求阶段威胁建模这件事,最难的不是学会STRIDE或者画数据流,而是让团队愿意在一张白板前面认真问一句“这个需求如果被坏人盯上会怎样”。一旦这个问题被问出来,后面所有工具、模板、流程都是水到渠成。

最后再分享一个小技巧:如果你们是第一次尝试,拿一个中等复杂度的需求练手,不要直接挑最核心的登录模块;从一个能上线的次要功能开始,跑通一次全流程,团队就会自己开始问那句话了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 16:26:10

内部服务用gRPC,对外接口用REST:微服务架构的协议分工与实践

写这篇东西的起因,是有个做架构评审的下午,我连着被问了三次同一个问题:gRPC 和 REST 到底选哪个?每次我都得从“这俩不在一个维度”开始讲,讲到 HTTP/2、Protobuf、网关、契约、浏览器生态,最后对方总会恍…

作者头像 李华
网站建设 2026/10/21 16:25:40

从词袋到词向量:TextCNN与BiLSTM在新闻文本分类中的实战

1. 从词袋到词向量:为什么深度学习模型需要更“懂语义”的输入做新闻文本分类做到第五篇,很多人会卡在同一个地方:前面用TF-IDF加线性模型已经能跑到一个不错的分数,但再往上提就非常吃力了。我当初也是这个状态,线下验…

作者头像 李华
网站建设 2026/10/20 9:57:16

医院挂号就诊系统全栈实战:SpringBoot+Vue+MySQL毕设指南

1. 这个选题为什么值得做:先搞清楚它解决什么问题很多人在挑毕业设计题目的时候,第一反应是往“高大上”的方向冲——图像识别、推荐算法、语音交互。结果呢,算法原理讲不明白,工程实现做不出来,最后只能到处找现成代码…

作者头像 李华
网站建设 2026/10/19 1:19:17

基于SpringAI的在线考试主观题智能阅卷系统设计实践

做在线考试系统,最容易翻车的不是题库也不是组卷,而是阅卷。尤其主观题,一张卷子里有几道论述题和简答题,按传统方式让老师逐份批改,量大、耗时,而且两个老师打出的分可能差出一档。去年我在负责某个高校的…

作者头像 李华
网站建设 2026/10/18 23:31:23

模板代码生成工具:从元数据到可用接口的完整实现

1. 为什么需要模板代码生成工具:一大半重复代码其实不该手写做后端开发的朋友应该都有过这种体验:新项目启动,建表、写实体、写Mapper、写Service接口和实现、写Controller,然后前端再把列表页、表单页、弹窗、状态标签挨个撸一遍…

作者头像 李华
网站建设 2026/10/21 13:48:57

贪心算法实战:从陶陶摘苹果升级版掌握最优选择策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华