返回
security2026年7月4日1 分钟

Soatok的非正式威胁模型指南:从基础到实战

#威胁模型#网络安全#密码学#端到端加密#安全设计

1. 引言:为什么需要理解威胁模型

在经历了关于混合后量子密码学(Hybrid Post-Quantum Cryptography)的漫长而令人疲惫的对话、一些混蛋试图用端点攻击(endpoint attacks)来刁难端到端加密(end-to-end encrypted)消息应用、以及愚蠢政客推动更多“年龄验证”(age verification)废话后的论坛讨论之后,我清楚地意识到,“威胁模型”(threat model)这个词对大多数人来说是一个陌生的概念——除了作为一个流行词。

背景说明:这幅插图是在反疫苗失败者声称“自己做研究”并短暂地将“威胁模型”作为流行词时委托创作的。即使没有这个背景,我仍然觉得它有点好笑。

坦白说:如果你来这里是为了寻找一份包含100多篇引用的学术资源,用于为你的涉及多个区块链的新创业公司编写正式的威胁模型文档,那么这个同性恋毛茸茸博客可能不适合你。也许你可以从STRIDE和系统理论(system theory)开始。但如果你想从零开始建立对好威胁模型应回答哪些问题的直觉,那你可能来对地方了。那么,让我们来谈谈威胁建模。

2. 新手入门:威胁模型的基础

在高层次上,不要过度思考。虽然威胁模型是一个正式的网络安全流程,一些信息安全专家确实专门从事此工作,但你可以在开发新产品或服务的设计和架构阶段运行非正式的威胁模型,没人能阻止你。你最终可能会得到更好的结果。

一个威胁模型至少应回答以下基本问题:

  • 我们到底在保护什么?如果你无法回答这个问题,你还有很多基础工作要做。
  • 谁/什么想要伤害我们保护的东西?黑客、活动家、网络跟踪者、社交媒体骚扰网络;自然灾害/坏运气;薪酬过低且过度劳累而厌倦的员工;被大型企业游说者收买以通过伤害所有人的愚蠢法律的愚蠢立法机构;国家对手(Nation State Adversaries)!!!
  • (2)如何攻击(1)?攻击场景在这里;墨菲定律(Murphy's Law)也在这里。
  • 我们将采取什么措施来防止(3)发生?墨菲定律也在这里!

如果你能勾选这些,你的文档在某种意义上可以称为威胁模型。然而,这在实践中往往毫无用处,因为一些关键细节被遗漏了。

  • 资产(1)之间如何关联/连接?用图(graphs)思考,而不是列表(lists)。并非所有目标都具有同等价值。
  • 我们做出了哪些假设,特别是关于(4)和(5)?我将在下面详细说明。
  • 我们故意不处理哪些威胁?你实际上无法应对任何人在不可预见的未来可能想象的每一种可能的攻击,所以不要假装能做到。

讽刺的是,太多人想当然地对待假设(6),但明确你的假设极其重要。如果你的一个假设是错误的,那么你的模型(充其量)是不完整的,或者你需要重新考虑你的已接受风险(7)列表。

例如:隐形蝾螈攻击(Invisible Salamanders attack)破坏了一些端到端加密消息设计中的滥用报告功能,但前提是你引入了滥用报告。这种攻击之所以可能,是因为相关AEAD方案(AES-GCM、ChaCha20-Poly1305)中的一个假设是:给定消息只有一个有效密钥。一旦你为给定消息引入了多个有效密钥(或就此而言的混淆代理),你就超出了算法的安全保证——这对攻击者来说是一个有趣的把戏。明确你的假设可以让你识别自己的未知未知(unknown unknowns)。你不需要完美。事实上:威胁模型应该是活的文档,而不是时间点快照。在你认为合适的时候更新它们。

3. 如何开始:实用步骤

如果你希望专业地进行威胁建模,你可能想阅读《威胁建模宣言》(Threat Modeling Manifesto)。以下是我的方法。

首先,以上述7个项目为格式写下来,以便你能快速复制粘贴。你会需要它。

接下来,在一大张方格纸(最好是)或数字等效物上,绘制你正在设计或分析的系统的组件。如果任何小部件直接与另一个小部件通信、依赖或交互,你需要以对你最有用的任何惯例绘制这种关系。

一旦设置完成,你想在整个图周围画一个框,然后假装你在玩《堡垒之夜》(Fortnite):每隔一段时间,框会缩小并更聚焦于每个单独的组件。每次迭代,记录每个组件的所有输入和输出,并尝试尽可能多地回答7个项目。重复,直到你深入到你的抽象允许的程度,然后集思广益,思考你对未深入挖掘的层有哪些假设。

你正在做的是从最高层开始,逐步深入到更具体的部分。你的数据库可能不像你的负载均衡器那样依赖X25519的安全性。但你的数据库也可能不应该内置RSS feed。注意不适当的关系,并尽可能切断它们。

4. 实例:我自己的工作

你可能已经知道,我正在为联邦宇宙(Fediverse)提供密钥透明度(key transparency)。这项工作在publickey.directory上跟踪,如果你在这篇博客发布后对其状态感兴趣的话。

这项工作始于一份规范(specification),其中包含一个突出的威胁模型。该威胁模型组织成以下部分:

  • 假设(Assumptions)(事先声明)
  • 资产(Assets)
  • 参与者(Actors)(包括攻击者和我们想要保护的人),赋予角色名称
  • 风险(Risks),具有四种状态之一:
    • 通过设计预防(Prevented by design):攻击根本不会成功 lol 😀
    • 缓解(Mitigated):攻击不应成功,除非假设错误。研究人员最感兴趣关注。
    • 可处理(Addressable):有一种缓解风险的方法,但需要努力或小心。操作员应意识到这一点。
    • 开放(Open):这是我们无法或不会缓解的风险。这些是将会成功的攻击。

当然,这个威胁模型并不完美。我没有以人类可读的图完美地将资产和参与者相互关联。风险部分可能存在我从未考虑过的盲点。我可能忘记写下对系统安全至关重要的某个假设。如果你能查看我项目的威胁模型并看到其缺点,你可能已经足够理解这项任务,可以自己编写了。

但足够隐晦的无耻自我推销了。只看我的例子,你学不到太多。我们还需要一个糟糕威胁模型文档的例子,而我正好有一个准备好了。

5. 反面教材:Matrix的威胁模型

我之前批评过Matrix(两次),所以如果你读过那些博客,这不会是新消息。这是Matrix的威胁模型(最新版v1.18):

  1. 安全威胁模型 9.1 拒绝服务(Denial of Service) 攻击者可能试图阻止向受害者传递消息,以便:
  • 干扰商业竞争对手的服务或营销活动。
  • 审查讨论或审查讨论中的参与者。
  • 进行一般性破坏。 9.1.1 威胁:资源耗尽(Resource Exhaustion) 攻击者可能导致受害者的服务器耗尽特定资源(例如,开放的TCP连接、CPU、内存、磁盘存储)。 9.1.2 威胁:不可恢复的一致性违规(Unrecoverable Consistency Violations) 攻击者可能发送消息,在集群中创建不可恢复的“脑裂”(split-brain)状态,使得受害者的服务器无法再推导出聊天室状态的一致视图。 9.1.3 威胁:不良历史(Bad History) 攻击者可能说服受害者接受无效消息,然后受害者将其包含在聊天室历史视图中。聊天室中的其他服务器将拒绝无效消息,并可能拒绝受害者的消息,因为它们依赖于无效消息。 9.1.4 威胁:阻止网络流量(Block Network Traffic) 攻击者可能试图在受害者的服务器与聊天室中的部分或所有其他服务器之间设置防火墙。 9.1.5 威胁:高消息量(High Volume of Messages) 攻击者可能向聊天室发送大量消息,使聊天室无法使用。 9.1.6 威胁:未经必要授权禁止用户(Banning users without necessary authorisation) 攻击者可能试图在没有必要授权的情况下禁止用户加入聊天室。 9.2 欺骗(Spoofing) 攻击者可能试图发送声称来自受害者的消息,而受害者并未发送该消息,以便:
  • 在进行非法活动时冒充受害者。
  • 获取受害者的特权。 9.2.1 威胁:更改消息内容(Altering Message Contents) 攻击者可能试图更改来自受害者的现有消息的内容。 9.2.2 威胁:虚假消息“origin”字段(Fake Message “origin” Field) 攻击者可能试图发送一条声称来自受害者的新消息,并带有虚假的“origin”字段。 9.3 垃圾信息(Spamming) 攻击者可能试图向受害者发送大量请求或未经请求的消息,以便:
  • 寻找诈骗受害者。
  • 推销不需要的产品。 9.3.1 威胁:未经请求的消息(Unsolicited Messages) 攻击者可能试图向不希望接收消息的受害者发送消息。 9.3.2 威胁:辱骂性消息(Abusive Messages) 攻击者可能向受害者发送辱骂或威胁性消息。 9.4 间谍活动(Spying) 攻击者可能试图访问由受害者发送或发送给受害者的消息内容或元数据,而这些消息本不应到达攻击者,以便:
  • 获取敏感的个人或商业信息。
  • 使用消息中包含的凭据冒充受害者(例如,密码重置消息)。
  • 发现受害者与谁交谈以及何时交谈。 9.4.1 威胁:传输过程中泄露(Disclosure during Transmission) 攻击者可能试图在服务器之间传输过程中暴露消息内容或元数据。 9.4.2 威胁:向聊天室外服务器泄露(Disclosure to Servers Outside Chatroom) 攻击者可能试图说服聊天室内的服务器将消息发送到其控制的、未被授权加入聊天室的服务器。 9.4.3 威胁:向聊天室内服务器泄露(Disclosure to Servers Within Chatroom) 攻击者可能控制聊天室内的服务器,以暴露该房间中消息的消息内容或元数据。

浏览这个列表时,你可能会注意到几点:

  • 这只是一个不同攻击类型的列表。
  • 没有假设列表。
  • 没有资产列表,也没有资产之间的关系。
  • 攻击列表严重不完整。
  • 尽管人们推崇Matrix优于其他E2EE信使,但其威胁模型对密码学或密钥管理只字未提。
  • 额外观察:自v1.1(2021年发布)以来,它基本保持不变,尽管我披露了漏洞,Lotte也进行了两次额外的密码学攻击。

尽管这很烦人,而且很容易完全否定Matrix,但至少他们有一个威胁模型。相比之下,Signal给你一堆技术规范,期望你自己弄清楚威胁模型。这是Signal让我恼火的众多事情之一。

所以,对于Matrix的威胁模型作者,我授予以下评价:Matrix的威胁模型?我给它C-。一个糟糕的威胁模型胜过没有威胁模型。

6. 威胁模型如何帮助你构建更好的东西

在你的职业生涯早期,你会听到许多信息安全真理。比如,“防御者必须永远正确,攻击者只需正确一次。”是的,但装备精良的防御者可以决定战场。把它放进你的《孙子兵法》里并抽上一口。

从这里的每个安全从业者到seclists,都宣扬纵深防御(defense-in-depth),但实际进行纵深防御意味着充分理解你的威胁模型,迫使攻击者进入可预测的死胡同。让我先给你一个实际例子,然后是一个更有趣的例子。

防止凭证填充(Credential Stuffing) 凭证填充是一种愚蠢简单的攻击,在大多数现实场景中却异常有效。为什么?因为人们重复使用密码。为什么人们重复使用密码?因为他们只能记住这么多密码,要求他们为你的应用创建唯一、安全的密码是可笑的。

为了缓解这种风险,很长一段时间内,密码管理器(password managers)是解决这个问题的正确答案。如今,它们仍然可以(但不是Lastpass),但通行密钥(passkeys)更好。为什么?因为通行密钥是一种更用户友好(注意:并非完全用户友好)的方式,让用户使用非对称密码学进行身份验证。在最佳情况下,他们使用硬件安全令牌(例如,SoloKeys或YubiKeys)。在一般情况下,他们的操作系统或密码管理器会为他们提供这一点。

像这样沿着“为什么?”问题的链条走,是感受一个(有严重缺陷的)安全控制所固有威胁的一种方式。但这确实伴随着陷入兔子洞的固有风险,所以要小心。

如果你想避免凭证填充和相关琐碎攻击:

  • 设计你的应用要求使用通行密钥。
  • 要求用户注册多个通行密钥(或至少一个用于备份目的)。
  • 给管理员一种方法,在用户丢失所有凭据时,通过紧急方式为另一个用户添加新的通行密钥。
  • 以管理员无法审查的方式记录这些操作。
  • 如果可能,完全不要支持密码进行身份验证。用于派生加密密钥的密码是可以的,正如我在这里所写的。

额外好处:通行密钥也是不可钓鱼的(not phishable)——由于协议在注册期间将每个凭据密码学绑定到域名。无论你让用户使用通行密钥花费多少成本,你都会在凭证填充和钓鱼(以及完全避免那些不能可衡量改善结果的愚蠢“钓鱼测试”)引起的支持负担上节省更多。通过消除人类记忆且永不重复使用高熵秘密的不合理期望,你消灭了多类攻击并提高了可用性。一个好的威胁建模练习可以独立于我的博客文章导致这一发现。

以可用性为代价的安全是以安全为代价的。——Avi Douglen

下一个例子更有趣,但也稍微高级一些。

7. 分布式端到端加密的挑战

目前,密码学专家和去中心化爱好者正在讨论两种用于直接消息的端到端加密提案:

  • ActivityPub E2EE规范,旨在为联邦宇宙软件(例如Mastodon)提供私人DM。
  • 像Germ Network这样的项目,希望为ATProto(例如BlueSky)做同样的事情。

这两个项目在某个时候都考虑使用MLS作为其E2EE会话密钥管理协议。然而,在非中心化系统中使用MLS有两个重要的注意事项,使得安全性不那么直接。

  • MLS指定了一个称为认证服务(Authentication Service)的抽象概念,SimpleX的负责人以公开尴尬的方式误解了它。我提出的密钥透明度方案是解决这个问题的一种方法,而无需创建中心化权威。
  • 消息排序对于支撑MLS中epoch的棘轮树(ratcheting trees)的安全性很重要。对于ActivityPub,如果他们采用密钥透明度来解决第一个注意事项,他们只需要明确如何处理来自多个提议的KeyUpdate消息的竞争,特别是跨不同服务器。这并非微不足道,但可以解决。

但对于ATProto / BlueSky来说,情况更棘手。

为什么ATProto使这更困难 ATProto没有像联邦宇宙那样的实例。部分原因是ATProto是由受Jack Dorsey雇佣的比特币中毒开发者设计的,他们决定拥有“全局状态”(global state)是一个好的服务设计选择。而区块链是最糟糕的全局状态稳定方式,因为你有许多写入者。

在进行安全分析时,你基本上必须将所有东西视为点对点(或接近p2p),而不是仅仅构建一个客户端用来加密传递给其实例的消息的东西(如ActivityPub)。这意味着你需要找出另一个复杂的协议来保证分布式系统中的消息排序(例如,像Raft共识算法这样的东西),或者你跳过MLS,转而使用成对E2EE,完全放弃组抽象。

威胁建模如何帮助 如果你认为用户之间传递的消息的机密性是你项目的安全目标,并且你希望你的托管是去中心化的,那么受区块链启发的ATProto设计实际上阻碍了使用当今标准化最有效的组密钥协议。是的,这是一个阻碍,目前几位优秀的工程师正在巧妙地解决它,但如果你还在绘图板上,你本可以避免他们的错误。

8. 威胁模型的不实用用途与总结

好吧,如果你读到这里,希望你已经理解:

  • 什么是威胁模型
  • 一个好的威胁模型应该包含什么
  • 如何发现糟糕的威胁模型
  • 威胁模型如何帮助你构建更好的东西

这些都是实用、有用的东西,但可能会有点枯燥。如果我告诉你,提升你的威胁建模技能可以让你在技术讨论中更好地嗅出废话呢?

后量子密码学的威胁建模 我最近写了一篇关于混合后量子构造(hybrid post-quantum constructions)的博客,讨论了签名而不是后量子KEM。碰巧的是,IETF的TLS工作组邮件列表上正在发生一个Last Call,Daniel J. Bernstein不帮忙地决定通过召集Twitter随机用户和其他阴谋论者来试图进行草根运动,谴责它。我没有夸张。

像这样的帖子引发了DJB的帖子:“我强烈反对NSA的提议。Patrick Timothy Dalrymple,LYRIA创始人兼CEO,IETF TLS邮件列表存档。”或者,可能是迄今为止最愚蠢的:“不要发布这份文档。启用国家SIGINT伤害所有人。——Willow,IETF TLS邮件列表存档。”

除了明显不合理的人(以及不受欢迎的性害虫如Jacob Appelbaum,我拒绝与之交流),我确实要求DJB召集到线程中的许多人详细说明他们具体的安全担忧。不出所料,他们遵循着同样的非黑即白思维(“混合好!纯PQ坏!”),正如我所怀疑的,但你总是需要探查,以防有意外原因!

为了将我们对威胁建模的理解应用于这种情况,我们需要确定一些事实:

  • ML-KEM不是NSA的设计。其主要提交者是Peter Schwabe,他与Daniel J. Bernstein合作开发了NaCl密码学库,并居住在德国。其他提交者遍布欧洲。
  • 信息论排除了ML-KEM的后门。参见:Sophie Schmieg。
  • ML-KEM是通过一个非常公开的十年国际努力被选为标准化的。
  • NIST / FIPS / NSA在分类系统中要求非混合ML-KEM / ML-DSA。如果这些算法中存在NOBUS后门,它将会……

🔗 原文链接:https://soatok.blog/2026/06/30/soatoks-informal-guide-to-threat-models/