2. 可信启动流程:BIOS/UEFI信任链、Bootloader验证、内核完整性校验
说到可信启动,我脑子里第一个蹦出来的画面,是几年前在机房调试一台服务器。那台机器怎么都起不来,最后发现是Bootloader被篡改了。嗯,从那以后,我对启动链的每一个环节都格外敏感。
说白了,可信启动就是一套「接力棒」机制。从硬件复位开始,每一级软件在交出控制权之前,都要先验明下一级的「正身」。只要有一环断了,整条链就不可信。
2.1 信任根与信任链模型
信任链的起点,叫信任根。它必须是物理上不可篡改的。在PC平台上,这个根就是BIOS或UEFI固件中的一段只读代码。
核心原则:度量在前,执行在后。先测量下一级代码的哈希值,跟预期值比对,一致了才跳转过去执行。
我习惯把信任链画成一条单向的箭头链:
- 信任根(Root of Trust) — 硬件固件,不可更改
- BIOS/UEFI 固件 — 度量Bootloader
- Bootloader — 度量操作系统内核
- 操作系统内核 — 度量内核模块和关键服务
你想想看,如果Bootloader被改了,它加载的内核再干净也没用。因为恶意代码在度量之前就已经被执行了。
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的签名。这样一来,信任链就变成了:
- UEFI固件验证shim的签名(微软证书)
- shim验证GRUB2的签名(发行版证书)
- 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值清零。这时候所有度量记录都失效了,需要重新建立信任基线。
嗯,信任链这东西,看着简单,实际维护起来细节很多。但只要理解了「度量在前,执行在后」这个核心原则,大部分问题都能找到根因。