威胁建模入门:从“谁会攻击我”开始
做安全设计这么多年,我越来越觉得,威胁建模是整个安全工作的“第一性原理”。你想想看,连谁会攻击你、怎么攻击你都没想清楚,后面做的所有防护措施,很可能都是白费功夫。
说白了,威胁建模就是一场“红蓝对抗”的桌面推演。我们站在攻击者的角度,系统地找出系统里最薄弱的地方。我个人习惯,每个新项目启动时,第一件事就是拉上架构、固件、验证的同事,关上门做一次威胁建模。
威胁建模到底为了什么?
我遇到过不少团队,上来就堆安全模块——加PUF、上加密引擎、做安全启动。结果呢?流片回来发现,攻击者根本不需要破解这些高级模块,直接从调试接口就把固件读走了。
威胁建模的目的,其实就三个:
- 提前发现漏洞:在设计阶段就把问题揪出来,而不是等流片后再打补丁
- 确定防护优先级:资源有限,先防最要命的攻击路径
- 建立安全共识:让硬件、软件、验证团队对“什么该防”达成一致
核心观点:威胁建模不是一次性的文档工作,而是贯穿整个芯片开发周期的持续活动。从架构定义到后端实现,每个阶段都要重新审视威胁模型。
STRIDE模型详解:微软的六把“安全手术刀”
STRIDE是微软提出来的威胁分类方法。我最早接触它是在做Windows硬件安全的时候,后来发现这套框架用在芯片安全上同样顺手。它把威胁分成六类,每类对应一种安全属性。
| 威胁类型 | 英文 | 破坏的安全属性 | 芯片场景举例 |
|---|---|---|---|
| S - 假冒 | Spoofing | 身份认证 | 伪造JTAG调试器身份,绕过安全调试认证 |
| T - 篡改 | Tampering | 完整性 | 修改Flash中的固件镜像,注入恶意代码 |
| R - 抵赖 | Repudiation | 不可否认性 | 攻击者执行了敏感操作,但日志无法追溯是谁干的 |
| I - 信息泄露 | Information Disclosure | 机密性 | 通过侧信道攻击提取AES密钥 |
| D - 拒绝服务 | Denial of Service | 可用性 | 向总线发送大量无效请求,导致安全CPU无法响应 |
| E - 权限提升 | Elevation of Privilege | 授权 | 利用缓冲区溢出从用户态跳转到安全监控模式 |
S - 假冒(Spoofing)
假冒就是“装成别人”。在芯片里,最常见的场景就是伪造调试接口的身份。我记得有个项目,调试控制器只检查了外部输入的ID,但没有做双向认证。结果攻击者直接伪造了一个合法ID,就把整个芯片的调试权限拿到了。嗯,从那以后,我要求所有调试接口必须做Challenge-Response认证。
T - 篡改(Tampering)
篡改针对的是数据的完整性。攻击者可能修改固件、配置寄存器,甚至篡改总线上的数据。我曾经见过一个案例,攻击者通过电压毛刺干扰了Flash读取,让CPU加载了被篡改的启动代码。防篡改,光靠校验和是不够的,得用带密钥的MAC或者数字签名。
R - 抵赖(Repudiation)
抵赖威胁在芯片里容易被忽视。说白了,就是出了事找不到责任人。比如,安全CPU执行了一条高危指令,但审计日志里只记录了“CPU执行了指令”,没有记录是谁发起的。我个人习惯,所有安全关键操作都必须绑定发起者的身份标识,并且日志要防篡改。
I - 信息泄露(Information Disclosure)
这是硬件安全的重灾区。密钥、固件、用户数据,都是攻击者的目标。侧信道攻击、内存残读、调试接口泄露,都是常见手段。我做过一个安全芯片,加密引擎的功耗曲线居然能直接看出密钥的汉明重量——这就是典型的信息泄露。
D - 拒绝服务(Denial of Service)
拒绝服务攻击的目标是让芯片“罢工”。比如,向安全DMA控制器发送海量请求,占满所有通道,导致正常的安全服务无法响应。在车规芯片里,这种攻击可能导致安全气囊在关键时刻无法触发——后果很严重。
E - 权限提升(Elevation of Privilege)
权限提升是攻击者的“终极目标”。从普通用户模式,一路打到安全监控模式,甚至拿到物理访问权限。我遇到过最典型的案例,是一个SoC的MMU配置有漏洞,非安全世界的程序通过精心构造的页表,读到了安全世界的内存。
我的经验:STRIDE的六类威胁不是孤立的。很多时候,攻击者会组合使用。比如,先通过信息泄露拿到密钥(I),然后用这个密钥篡改固件(T),最后实现权限提升(E)。做威胁建模时,一定要考虑攻击链。
如何识别资产与信任边界?
识别资产和信任边界,是威胁建模的“地基”。地基没打好,后面的分析全是空中楼阁。
第一步:列出所有资产
资产就是攻击者想要的东西。在芯片里,资产通常包括:
- 密钥材料:根密钥、设备密钥、会话密钥
- 固件/软件:Boot ROM、安全固件、应用程序
- 敏感数据:用户身份信息、支付凭证、生物特征
- 硬件资源:调试接口、安全CPU、加密引擎、OTP存储器
- 功能安全:安全状态机、看门狗、错误报告机制
避坑指南:我曾经犯过一个错误——只列出了“明显”的资产,比如密钥和固件。结果忽略了调试日志里的敏感信息。攻击者从日志里分析出了芯片的启动序列,成功绕过了安全启动。记住:任何可能被攻击者利用的信息,都是资产。
第二步:画出信任边界
信任边界,是不同安全等级之间的“分界线”。在芯片里,常见的信任边界包括:
- 芯片边界:芯片内部 vs. 外部世界(PCB、传感器、通信接口)
- 安全域边界:安全世界 vs. 非安全世界(基于TrustZone或同类技术)
- 特权级边界:用户模式 vs. 监管模式 vs. 安全监控模式
- 总线边界:不同总线域之间的桥接点
- 电源域边界:常开域 vs. 可关断域
我个人习惯,在架构图上用红色虚线标出所有信任边界。每一条虚线,都意味着数据在跨越时需要进行安全检查——比如权限验证、加密传输、完整性校验。
第三步:分析跨边界的数据流
有了资产和信任边界,接下来就是看数据怎么在这些边界之间流动。每个数据流,都可能成为攻击者的“突破口”。
举个例子:非安全世界的应用程序,通过共享内存向安全世界发送一个加密请求。这个数据流跨越了安全域边界。我们需要问自己:
- 共享内存的权限配置是否正确?
- 请求格式是否经过严格校验?
- 安全世界处理完结果后,会不会把敏感数据残留在共享内存里?
威胁建模的输出:一份可执行的威胁清单
做完上面的分析,最终要产出一份威胁清单。这份清单不是写完了就束之高阁的文档,而是后续安全设计的“输入”。
我一般要求团队按这个格式输出:
| 威胁ID | STRIDE类型 | 威胁描述 | 影响资产 | 风险等级 | 缓解措施 |
|---|---|---|---|---|---|
| T-001 | 假冒 | 攻击者伪造调试器身份,获取芯片调试权限 | 调试接口、固件 | 高 | 实现Challenge-Response双向认证 |
| T-002 | 篡改 | 攻击者通过电压毛刺篡改Flash中的启动代码 | Boot ROM、固件 | 高 | 增加电压/频率检测器,启动代码使用数字签名 |
| T-003 | 信息泄露 | 加密引擎的功耗曲线泄露密钥信息 | AES密钥 | 中 | 引入掩码/随机化技术,增加功耗噪声 |
小技巧:风险等级可以用DREAD模型来评估——Damage(损害)、Reproducibility(可复现性)、Exploitability(可利用性)、Affected Users(受影响用户)、Discoverability(可发现性)。每个维度打分1-10,总分越高,优先级越高。
好了,威胁建模入门就讲到这里。记住,威胁建模不是“做完一次就完事”的。芯片设计过程中,架构在变、接口在变、软件在变,威胁模型也要跟着变。养成习惯,每次设计评审都带上威胁建模的视角——你会发现,很多安全问题在设计阶段就被扼杀在摇篮里了。