3. 防回滚核心概念
固件防回滚的本质,是让设备在启动和升级过程中始终只接受“版本不低于当前已授权版本”的镜像。要理解这一点,需要先看清回滚攻击的原理,再依次掌握防回滚定义、安全版本号、单调计数器以及信任根与信任链在其中的作用。这些概念彼此咬合,缺一不可。
一、回滚攻击原理:把旧漏洞重新请回来
回滚攻击(Rollback Attack)并不是破解新固件,而是诱导设备重新运行一个旧的、已签名的、但存在已知漏洞的固件版本。攻击者通常无法伪造合法签名,却能合法地拿到厂商历史版本镜像,然后通过降级通道、恢复模式、OTA 重放或物理刷写,把设备“退回”到旧版本。
其危害在于:新版本修复的漏洞在旧版本中依然存在。攻击者一旦成功回滚,就能利用旧漏洞提权、绕过校验、植入持久化后门,甚至再借旧版本漏洞重新刷入恶意镜像。因此回滚攻击常被用作“漏洞复活”的跳板,而不是最终目的。
典型攻击路径包括:
- 降级重放:截获旧版 OTA 包,重复推送给设备,若设备只验签名不验版本,就会接受。
- 恢复模式滥用:利用 U-Boot、Fastboot 或恢复分区刷入旧镜像,绕过正常升级流程。
- 双分区回滚:A/B 分区中保留旧版本,通过切换启动槽位回退到旧固件。
- 版本号篡改:若版本号存储可写且无完整性保护,攻击者直接改小版本号再刷旧包。
二、防回滚定义与安全版本号
防回滚(Anti-Rollback)是指设备在启动或升级时,强制要求待加载固件的安全版本号不低于设备当前记录的最低允许版本号,从而拒绝任何降级行为的安全机制。它保护的不是“固件是否被篡改”,而是“固件是否足够新”。
安全版本号(Security Version Number, SVN)是防回滚的判定依据。它与普通语义版本号(如 1.2.3)不同:语义版本号用于功能迭代,可升可降;SVN 是单调递增的安全计数器,只允许增大,不允许减小。每次修复关键漏洞并发布新固件时,厂商会提升 SVN,并在签名元数据中绑定该值。
核心判定式:if (firmware_svn < device_min_svn) reject();
设备只记录“最低允许版本”,而不是“当前运行版本”,这样即使运行版本被回退,门槛依然存在。
三、单调计数器:让版本号无法被回退
如果 SVN 只存在普通 Flash 中,攻击者可以把它改小,防回滚就形同虚设。因此 SVN 必须存放在单调计数器(Monotonic Counter)中。单调计数器的特性是:只能递增,不能递减;一旦写入新值,旧值不可恢复。
常见实现方式包括:
- OTP/eFuse:一次性可编程熔丝,烧写后不可更改,适合存放最低允许 SVN。
- 安全芯片计数器:如 TPM、ATECC、SE 中的单调计数器,由硬件保证只增不减。
- 受保护存储 + 完整性校验:用 HMAC 或签名保护计数器值,防止篡改,但安全性弱于硬件计数器。
单调计数器解决了“版本号可被改小”的问题,使防回滚从“软件约定”升级为“硬件强制”。
四、信任根与信任链在防回滚中的作用
防回滚的判定逻辑本身也必须被信任。如果校验代码被替换,再强的 SVN 也无意义。因此防回滚必须建立在信任根(Root of Trust, RoT)之上:RoT 是设备中不可篡改的信任起点,通常由 BootROM、硬件密钥和 OTP 组成。
信任链(Chain of Trust)则把信任从 RoT 逐级传递:BootROM 验证一级引导,一级引导验证二级引导,逐级直到应用固件。在每一级验证中,除了校验签名,还要校验 SVN 是否满足最低要求。这样,防回滚检查被嵌入信任链的每一环,任何一级降级都会被拒绝。
五、关键概念对照与常见误区
| 概念 | 作用 | 典型载体 | 常见误区 |
|---|---|---|---|
| 安全版本号 SVN | 判定固件是否允许加载 | 签名元数据、镜像头 | 与语义版本号混用,认为功能版本高就安全 |
| 单调计数器 | 保证 SVN 门槛只增不减 | eFuse、OTP、安全芯片 | 用普通 Flash 存储,可被改小 |
| 信任根 RoT | 提供不可篡改的信任起点 | BootROM、硬件密钥 | 认为签名验证就足够,忽略 RoT 被替换 |
| 信任链 | 逐级传递信任并执行 SVN 检查 | BL1→BL2→APP | 只在应用层做防回滚,引导层被绕过 |
常见误区:很多团队只在 OTA 服务端做版本判断,设备端不校验 SVN。攻击者一旦绕过服务端直接刷写,防回滚立即失效。正确做法是:设备端在信任链每一级都执行 SVN 检查,且最低允许版本存放在单调计数器中。
六、案例场景:一次降级刷写被拦截
某网关设备当前运行固件 SVN=8,eFuse 中记录 min_svn=7。攻击者通过恢复模式刷入 SVN=5 的旧固件,该固件存在命令注入漏洞。启动时 BootROM 读取 eFuse 中的 min_svn=7,验证 BL1 镜像头中的 SVN=5,判定 5<7,直接中止启动并记录安全事件。设备保持不可用状态,但旧漏洞无法被激活,攻击者也无法借此提权。
[BOOT] RoT: read min_svn from eFuse = 7
[BOOT] BL1 header svn = 5
[BOOT] anti-rollback check: 5 < 7 -> REJECT
[BOOT] secure boot halted, event logged
[BOOT] device remains on last trusted version
这个案例说明:防回滚不是“阻止刷写”,而是“阻止旧版本获得执行权”。即使镜像被写入,只要 SVN 不达标,信任链就不会把控制权交给它。
工程建议:SVN 的递增策略应写入发布流程,每次修复高危漏洞必须提升 SVN;同时保留回滚窗口时,应通过“允许的最低版本”而非“允许的旧镜像”来管理,避免把降级能力留在设备端。
综上,回滚攻击利用的是旧版本漏洞的复活;防回滚通过安全版本号建立判定标准,通过单调计数器保证标准不可篡改,再通过信任根与信任链保证判定逻辑本身可信。四者形成闭环,才能让设备在面临降级刷写时依然守住安全底线。