2. 固件安全基础

固件是运行在硬件与操作系统之间的底层软件,通常固化在 SPI Flash、eMMC、UFS 或 ROM 中,负责上电初始化、硬件自检、外设配置,并最终把控制权交给引导加载程序或操作系统。与普通应用软件不同,固件一旦被篡改,攻击者可以在操作系统安全机制生效之前获得执行机会,因此固件安全是整个可信计算链条的起点。理解固件防降级与回滚保护,必须先看清固件的组成、启动流程、信任根、安全启动与度量启动之间的关系,以及攻击者最常利用的入口。

一、固件概念与组成

典型设备的固件并非单一镜像,而是由多个阶段和多个存储区域组成。以嵌入式 Linux 或 Android 设备为例,常见组成包括:

  • Boot ROM:芯片出厂时固化的只读代码,是上电后执行的第一段程序,通常不可修改,承担最初始的信任锚点角色。
  • 一级引导程序(SPL/Preloader):初始化时钟、内存控制器、存储控制器,加载下一阶段引导程序。
  • 二级引导程序(U-Boot、LK、ABL 等):初始化更多外设,校验并加载内核与设备树。
  • 安全固件区:如 TEE OS、安全监控固件、电源管理固件、基带固件等。
  • 可变数据区:环境变量、回滚计数器、版本号、密钥槽、日志区等。

这些组件分布在不同的存储介质和分区中,启动时按固定顺序逐级加载。任何一级被替换或降级,都可能破坏后续所有安全假设。

二、启动流程与信任根

设备上电后,CPU 首先从固定地址取指,执行 Boot ROM 中的代码。Boot ROM 会读取启动介质中的第一阶段引导程序,验证其签名或校验值,验证通过后跳转执行。随后每一级引导程序验证下一级镜像,直到内核和系统分区。这个逐级验证的过程称为信任链,而信任链的起点就是信任根(Root of Trust, RoT)。

信任根通常由三部分构成:

  • 可信计算基:不可修改的 Boot ROM 代码。
  • 可信密钥:烧录在 OTP/eFuse 中的公钥哈希或根公钥。
  • 可信度量:由硬件或 ROM 代码计算出的初始摘要值。

信任根必须满足“不可篡改、可验证、可度量”三个条件。如果根公钥可以被替换,或者 Boot ROM 存在可跳过的验证分支,那么整条信任链就形同虚设。

核心原则:信任根不可变,信任链逐级传递,每一级只信任经过验证的下一级。

三、安全启动与度量启动

安全启动(Secure Boot)和度量启动(Measured Boot)经常被混淆,但二者目标不同。安全启动强调“验证通过才执行”,是一种强制门禁;度量启动强调“记录并报告”,是一种可审计的完整性证据。安全启动解决“能不能启动”,度量启动解决“启动了什么、是否可信”。

对比项 安全启动 度量启动
核心动作 验签、校验哈希、失败则阻断 计算摘要、扩展 PCR、记录日志
执行时机 每一级加载前 每一级加载前后均可
失败后果 停止启动或进入恢复模式 不直接阻断,但远端可判定异常
典型技术 RSA/ECDSA 签名、哈希白名单 TPM PCR、DICE、事件日志
防降级作用 可结合版本号拒绝旧镜像 可发现版本回退痕迹

在防降级场景中,安全启动通常需要引入版本号或安全计数器。仅验证签名是不够的,因为攻击者可以重新签名一个旧版本镜像,或者直接回滚到官方旧固件。只有把“版本不低于当前最低允许版本”作为验证条件之一,才能阻止回滚。

四、常见攻击面

固件攻击面贯穿启动全流程,常见入口包括:

  • Boot ROM 漏洞:如 USB 下载模式绕过、缓冲区溢出、验证分支跳过。
  • 引导程序配置错误:未锁定 fastboot、未关闭调试串口、环境变量可写。
  • 签名验证缺陷:只校验部分分区、哈希算法过时、公钥可替换。
  • 回滚攻击:刷入旧版有漏洞固件,再利用已知漏洞提权。
  • 物理攻击:SPI Flash 离线读写、eMMC 直接访问、故障注入。
  • 供应链攻击:生产工具、烧录镜像、OTA 服务器被污染。

常见误区:认为“开了安全启动就安全了”。实际上,安全启动只覆盖启动路径,若 OTA 更新流程、恢复模式或调试接口未纳入同一验证体系,攻击者仍可绕过。

五、场景复盘:一次典型的回滚攻击

某设备安全启动已开启,但版本校验仅比较字符串且允许降级。攻击者获取旧版固件后,通过官方 OTA 通道重新刷入。旧版固件中存在已修复的 fastboot 漏洞,攻击者随后解锁引导程序并刷入自定义内核,最终获取 root 权限。复盘发现三个问题:第一,版本号未与安全计数器绑定;第二,OTA 包未强制要求版本递增;第三,恢复模式未校验版本下限。修复方案是在 Boot ROM 之后的每一级验证中加入防回滚计数器,并将计数器存储在 OTP 或 TEE 保护区域,任何降级尝试直接拒绝启动。

# 典型安全启动验证伪代码
verify_image(image, pubkey, min_version):
    digest = hash(image.payload)
    if not verify_signature(digest, image.signature, pubkey):
        return REJECT
    if image.version < min_version:
        return REJECT_ROLLBACK
    return ACCEPT

从工程实践看,固件安全不是单点技术,而是“信任根 + 逐级验证 + 版本约束 + 度量记录 + 攻击面收敛”的组合。只有把启动流程中的每一级都纳入同一安全策略,防降级与回滚保护才有可靠基础。

固件启动信任链与攻击面示意 Boot ROM 信任根 · 不可修改 SPL / Preloader 时钟 · 内存 · 存储初始化 U-Boot / ABL 外设 · 内核加载 Kernel + DTB 内核 · 设备树 System / Vendor 根文件系统 · 应用 TEE / Secure OS 安全世界 · 密钥保护 验签 验签 验签 验签 常见攻击面 Boot ROM 漏洞 引导程序配置错误 签名验证缺陷 回滚攻击 物理攻击 供应链污染 调试接口未关闭 OTA 通道被劫持