2. 可信启动流程:BIOS/UEFI信任链、Bootloader验证、内核完整性校验

说到可信启动,我脑子里第一个蹦出来的画面,是几年前在机房调试一台服务器。那台机器怎么都起不来,最后发现是Bootloader被篡改了。嗯,从那以后,我对启动链的每一个环节都格外敏感。

说白了,可信启动就是一套「接力棒」机制。从硬件复位开始,每一级软件在交出控制权之前,都要先验明下一级的「正身」。只要有一环断了,整条链就不可信。

2.1 信任根与信任链模型

信任链的起点,叫信任根。它必须是物理上不可篡改的。在PC平台上,这个根就是BIOS或UEFI固件中的一段只读代码。

核心原则:度量在前,执行在后。先测量下一级代码的哈希值,跟预期值比对,一致了才跳转过去执行。

我习惯把信任链画成一条单向的箭头链:

  • 信任根(Root of Trust) — 硬件固件,不可更改
  • BIOS/UEFI 固件 — 度量Bootloader
  • Bootloader — 度量操作系统内核
  • 操作系统内核 — 度量内核模块和关键服务

你想想看,如果Bootloader被改了,它加载的内核再干净也没用。因为恶意代码在度量之前就已经被执行了。

可信启动信任链 信任根 硬件固件 BIOS/UEFI 度量Bootloader Bootloader 度量内核 内核 度量模块 信任链传递规则 1. 每一级只信任上一级的度量结果 2. 度量值存储在防篡改区域(如TPM PCR寄存器) 3. 任何一级度量失败,启动过程立即终止

2.2 BIOS vs UEFI:信任链的差异

BIOS和UEFI,虽然都承担信任根的角色,但实现方式差别很大。我在项目中遇到过不少因为混用两者概念导致的配置错误。

对比维度 BIOS(传统) UEFI(现代)
启动模式 实模式,16位 保护模式,32/64位
信任链起点 BIOS ROM中的POST代码 UEFI安全启动(Secure Boot)
度量方式 无标准度量,依赖硬件跳线 基于数字签名和证书链
Bootloader验证 通常不验证,直接加载MBR 验证签名后才加载EFI应用
可扩展性 差,依赖中断向量表 好,支持驱动和协议接口

我的建议:新项目一律用UEFI+Secure Boot。BIOS的信任链太脆弱了,MBR被改了你都不知道。我曾经帮一个客户排查启动异常,最后发现是MBR被引导扇区病毒覆盖了——BIOS根本不会报错。

2.3 Bootloader验证:GRUB2与shim机制

Bootloader是信任链中最容易被攻击的一环。为什么?因为它体积大、功能复杂、还经常被更新。

以Linux生态为例,GRUB2是主流。但GRUB2本身并不安全——它只是一个普通的EFI应用。真正的验证机制在它前面加了一层:shim。

shim是什么?说白了,它是一个微型的、经过微软签名的Bootloader。它的唯一任务就是验证GRUB2的签名。这样一来,信任链就变成了:

  1. UEFI固件验证shim的签名(微软证书)
  2. shim验证GRUB2的签名(发行版证书)
  3. GRUB2验证内核的签名

注意:shim本身也有版本问题。我记得有一次升级内核后系统起不来,查了半天发现是shim版本太旧,不认识新内核的签名算法。所以,shim和GRUB2要一起更新,别只升一个。

2.4 内核完整性校验

内核加载时,Bootloader会做两件事:

  • 度量:计算内核镜像的哈希值
  • 验证:比对哈希值与预期值,或验证数字签名

如果开启了IMA(Integrity Measurement Architecture),内核启动后还会继续度量后续加载的内核模块。这就像滚雪球一样,信任链越滚越长。

我习惯把内核完整性校验分为两个阶段:

阶段 执行者 度量对象 存储位置
启动前 Bootloader vmlinuz、initramfs TPM PCR[4]
启动后 内核(IMA) 内核模块、关键文件 TPM PCR[10]

关键点:内核完整性校验不只是防篡改,还要防降级攻击。攻击者可能用一个有已知漏洞的老版本内核替换新内核。所以,度量值必须包含版本信息。

2.5 实战:查看当前系统的信任链状态

说了这么多理论,来点实际的。怎么确认你的系统信任链是完整的?

我个人习惯用这几个命令:

# 查看UEFI安全启动状态
mokutil --sb-state

# 查看TPM PCR寄存器内容(需要root)
cat /sys/kernel/security/tpm0/ascii_bios_measurements

# 查看IMA度量日志
cat /sys/kernel/security/ima/ascii_runtime_measurements

如果Secure Boot是开启的,PCR寄存器里有值,IMA日志在增长,那你的信任链基本是健康的。如果发现PCR[4]是空的,或者IMA日志里出现「appraise: invalid」的条目,那就得警惕了。

一个小技巧:把PCR值记录下来,每次系统更新后比对一下。我写了个脚本,每次内核更新后自动比对PCR[4]的值,变了就发告警。这样即使攻击者绕过了签名验证,我也能第一时间发现。

2.6 常见问题与避坑指南

最后,分享几个我踩过的坑:

  • 双系统启动:Windows和Linux共用Secure Boot时,shim的证书可能被Windows更新覆盖。我曾经遇到过Windows更新后Linux进不去的情况,解决办法是重新注册shim的MOK。
  • 自定义内核:自己编译的内核没有发行版签名,需要手动签入MOK。别偷懒用「shim.efi --no-verify」,那等于把信任链断了。
  • TPM被重置:清空CMOS或更换主板会导致TPM PCR值清零。这时候所有度量记录都失效了,需要重新建立信任基线。

嗯,信任链这东西,看着简单,实际维护起来细节很多。但只要理解了「度量在前,执行在后」这个核心原则,大部分问题都能找到根因。