威胁建模:识别OTA更新中的威胁、攻击面分析、资产与信任边界
威胁建模这件事,说白了就是在攻击者动手之前,你先替他把路走一遍。我做了这么多年嵌入式安全,见过太多团队上来就撸代码、搞加密,结果上线第一天就被打穿——原因很简单:连自己的敌人是谁都没搞清楚。
这一章,我们就来聊聊OTA更新场景下,怎么系统地做威胁建模。我会结合STRIDE模型,把资产、攻击面、信任边界这些概念一个个拆开讲。嗯,都是我在项目里踩过的坑,希望能帮你少走弯路。
2.1 资产识别:你到底在保护什么?
先问自己一个问题:如果OTA更新被攻破,攻击者能拿到什么?
我个人习惯把资产分成三类:
- 固件镜像——这是最核心的资产。泄露了,产品逻辑就裸奔;被篡改了,设备就变成别人的肉鸡。
- 签名密钥——丢了密钥,整个信任体系就崩塌了。我在一个项目里见过有人把私钥硬编码在源码里,还上传到了GitHub……嗯,那场面,惨不忍睹。
- 设备身份——每台设备的唯一ID、证书、安全凭证。攻击者拿到这些,就能冒充合法设备,批量搞事情。
核心原则:资产的价值决定了防护的投入。固件签名密钥如果被泄露,整个产品线的安全就归零了。所以,密钥管理永远是第一优先级。
我建议你画一张资产清单表,把每个资产的存储位置、访问权限、生命周期都列清楚。这样后面做攻击面分析时,心里就有底了。
2.2 攻击面分析:攻击者从哪里下手?
攻击面,就是攻击者能接触到你的系统的地方。OTA更新的攻击面,说白了就是数据流动的每一个环节。
我把它归纳为四个主要入口:
| 攻击面 | 典型攻击方式 | 我在项目中遇到的案例 |
|---|---|---|
| 云端服务器 | SQL注入、API劫持、DDoS | 有一次客户的后台API没做鉴权,攻击者直接调接口给所有设备推送了恶意固件 |
| 通信链路 | 中间人攻击、重放攻击、降级攻击 | 我记得一个IoT项目,设备用HTTP下载固件,攻击者在WiFi热点上做了个代理,替换了固件包 |
| 设备本地 | 物理篡改、调试接口滥用、Bootloader绕过 | 曾经有个客户的产品,UART调试口没锁,攻击者直接通过串口刷入了恶意固件 |
| 固件包本身 | 逆向工程、植入后门、签名伪造 | 嗯,这个我后面会细讲,先卖个关子 |
你想想看,这四个面里,哪个最容易攻破?我个人经验是——通信链路。因为很多团队觉得“反正数据加密了”,就忽略了完整性校验和身份认证。结果呢?攻击者不破解你的加密,他直接替换你的固件包,设备照样能解包安装。
避坑指南:我曾经在一个项目中,团队只做了传输层加密(TLS),但没做固件包的数字签名。结果攻击者通过中间人攻击,替换了TLS握手后的明文固件包。设备解包时发现签名不对?不存在的,因为根本没签名。从那以后,我坚持“加密+签名”必须同时上,缺一不可。
2.3 信任边界:谁是可以信任的?
信任边界,就是你的系统里,哪些组件之间是互相信任的,哪些不是。说白了,就是画一条线,线内的东西你默认可信,线外的你默认不可信。
在OTA更新场景下,我习惯这样划分:
- 信任域1:安全硬件环境——比如HSM、TEE、安全元件。这些是硬件级别的信任根,代码和数据不会被外部篡改。
- 信任域2:Bootloader——它负责验证固件签名,是软件信任链的起点。Bootloader本身必须是只读的,或者由安全硬件保护。
- 信任域3:主应用——运行在普通执行环境中的固件。它信任Bootloader,但不信任网络数据。
- 不可信域:外部网络——云端、下载服务器、通信链路。这些你都不能信任,必须做完整性校验和身份认证。
为什么会这样划分?因为信任边界一旦模糊,攻击者就能跨域攻击。我记得有个项目,团队把固件解密密钥存在主应用的Flash里,结果攻击者通过漏洞读取了Flash,直接解密了所有固件包。这就是典型的信任边界没划清楚——主应用不应该持有解密密钥,密钥应该放在安全硬件里。
我的建议:画信任边界图时,用不同颜色的框表示不同信任域。红色框表示不可信,绿色框表示可信。然后检查每个跨边界的数据流——有没有做签名验证?有没有做加密?有没有做防重放?如果有一条数据流从红色框直接进入绿色框而没有经过任何校验,那这就是一个高危漏洞。
2.4 威胁建模实战:用STRIDE过一遍
好了,资产、攻击面、信任边界都理清了。接下来就是实战环节——用STRIDE模型系统性地识别威胁。
STRIDE是微软提出的威胁分类模型,每个字母代表一类威胁:
| 威胁类型 | 含义 | OTA场景举例 |
|---|---|---|
| Spoofing(假冒) | 攻击者冒充合法实体 | 伪造云端服务器,向设备推送恶意固件 |
| Tampering(篡改) | 攻击者修改数据 | 中间人攻击,替换固件包内容 |
| Repudiation(抵赖) | 攻击者否认做过某操作 | 设备更新失败后,云端无法证明曾推送过合法固件 |
| Information Disclosure(信息泄露) | 敏感数据被窃取 | 固件镜像被逆向,算法和密钥泄露 |
| Denial of Service(拒绝服务) | 系统不可用 | 攻击者发送大量无效更新请求,耗尽设备存储或带宽 |
| Elevation of Privilege(权限提升) | 攻击者获得更高权限 | 利用OTA漏洞从普通用户态提权到内核态,甚至Bootloader |
我个人习惯,每识别出一个威胁,就给它打一个风险等级(高/中/低),然后记录在威胁清单里。这样后面做安全设计时,就知道哪些威胁必须优先处理。
实战技巧:不要试图一次性覆盖所有威胁。我建议你先聚焦高风险的威胁——比如固件篡改和签名伪造。这两个如果没防住,其他防护做得再好也没用。低风险的威胁(比如抵赖)可以放到后续迭代中处理。
2.5 威胁建模框架图
下面这张图,是我做威胁建模时常用的框架。它把资产、攻击面、信任边界和STRIDE威胁串在了一起,方便你一目了然地看清全局。
这张图的核心思路很简单:先搞清楚你在保护什么(资产),再搞清楚攻击者从哪里下手(攻击面),然后划清哪些地方是可信的(信任边界),最后用STRIDE模型把威胁一个个揪出来。
嗯,这套流程我用了好几年,每次做新项目都走一遍。虽然前期花点时间,但后面做安全设计时,心里特别踏实。
2.6 威胁清单示例
最后,我分享一个我在项目中实际用过的威胁清单模板。你可以直接拿来用,也可以根据自己的场景调整。
| 威胁ID | 威胁描述 | STRIDE分类 | 风险等级 | 缓解措施 |
|---|---|---|---|---|
| T-001 | 攻击者通过中间人攻击替换固件包 | Tampering | 高 | 固件包数字签名 + 设备端签名验证 |
| T-002 | 攻击者伪造云端服务器推送恶意固件 | Spoofing | 高 | 双向TLS认证 + 证书固定 |
| T-003 | 攻击者通过调试接口绕过Bootloader | Elevation | 高 | 生产时熔断调试接口 + 安全启动 |
| T-004 | 攻击者逆向固件提取签名密钥 | Info Disclosure | 中 | 密钥存储在HSM/TEE中,代码混淆 |
| T-005 | 攻击者发送大量无效更新请求耗尽设备存储 | DoS | 中 | 更新请求频率限制 + 存储空间配额 |
我的习惯:威胁清单不是一次性写完就完事了。我建议每做完一轮安全测试,就回头更新一次清单。新发现的威胁加进去,已经缓解的威胁标记为“已处理”。这样你的威胁建模就是活的,而不是一份躺在文档里的死文件。