启动度量技术:从BIOS到内核的信任链
启动度量,说白了就是给计算机的启动过程装上一台「行车记录仪」。从你按下电源键那一刻起,系统到底跑了哪些代码?这些代码有没有被篡改?度量技术就是要把这些信息一一记录下来。
我个人习惯把启动度量比作「接力赛」——每一棒都要确认上一棒是可信的,然后自己再跑一段,把信任传递下去。今天我们就来拆解这个接力过程:BIOS/UEFI固件度量、BootLoader度量、内核度量,以及怎么读懂那些度量日志。
核心观点:可信启动不是「防攻击」,而是「可审计」。度量技术不阻止恶意代码运行,但它能确保——任何篡改都会留下证据。
BIOS/UEFI固件度量:信任链的起点
计算机通电后,第一个执行的代码是固件。传统BIOS也好,现代UEFI也罢,它们都是信任链的「第一棒」。如果这一棒出了问题,后面再怎么度量都是白搭。
我记得在2018年参与过一个金融项目,客户坚持要用传统BIOS启动。我当时的建议是:要么换UEFI,要么加TPM芯片做静态度量。为什么?因为传统BIOS的度量能力实在太弱了。
UEFI安全启动(Secure Boot)
UEFI Secure Boot是目前最主流的固件度量方案。它的工作原理其实不复杂:
- 固件中预置了「可信数据库」(db),里面存放着允许执行的签名证书或哈希值
- 每次加载UEFI驱动或引导程序时,都会验证其数字签名
- 验证失败?直接拒绝执行,不给任何机会
这里有个坑,我曾经踩过——Secure Boot开启后,如果你自己编译了一个GRUB,没签名就直接放进去,机器会直接黑屏。嗯,那会儿我还在想「怎么新装的内核起不来了」,折腾了半天才发现是签名问题。
小技巧:在开发和测试环境中,可以先把Secure Boot设为Setup Mode,这样允许加载未签名的EFI程序。但生产环境务必恢复User Mode,并只允许经过签名的代码运行。
TPM与平台配置寄存器(PCR)
TPM(可信平台模块)是固件度量的「账本」。它内部有一组PCR寄存器,专门用来存储度量值的哈希摘要。关键特性是:PCR的值只能扩展(extend),不能重置或覆盖。
扩展操作是这样的:PCR新值 = SHA256(PCR旧值 || 新度量值)。你想想看,这意味着什么?意味着只要度量序列不同,最终的PCR值就不同。攻击者想伪造一个合法的PCR值?几乎不可能。
| PCR索引 | 度量内容 | 我的经验 |
|---|---|---|
| PCR 0 | 固件代码(BIOS/UEFI) | 这个值在硬件不变时是固定的,适合做基线 |
| PCR 1 | 固件配置 | 改BIOS设置会导致它变化,注意区分 |
| PCR 2 | Option ROM代码 | 网卡、RAID卡的固件也在这里 |
| PCR 4 | MBR/GPT引导记录 | 传统BIOS启动时用,UEFI下不常用 |
| PCR 5 | MBR/GPT引导配置 | 配合PCR 4使用 |
| PCR 7 | Secure Boot策略 | 我常用它来验证Secure Boot是否被关闭 |
注意:TPM的PCR值在系统休眠恢复后可能会变化。如果你在做远程证明,一定要考虑这个场景。我曾经因为这个原因,导致一批服务器的远程证明全部失败,排查了两天才找到原因。
BootLoader度量:GRUB的信任接力
固件把控制权交给BootLoader后,度量工作不能停。GRUB 2是目前Linux世界最主流的引导程序,它本身也支持度量功能。
GRUB的度量分为两个阶段:
- 第一阶段:GRUB自身被UEFI度量(通过shim或直接签名)
- 第二阶段:GRUB加载内核和initramfs时,会调用TPM的
tpm2_extend命令,把度量值写入PCR
我建议你在GRUB配置中开启measure选项。具体做法是编辑/etc/default/grub,在GRUB_CMDLINE_LINUX中加入:
GRUB_CMDLINE_LINUX="... tpm2_tis=1 tpm2_extend_pcr=8,9,10"
然后运行update-grub。这样GRUB在加载每个模块时,都会把度量值扩展到指定的PCR中。
这里有个细节——GRUB的度量日志默认不保存到文件系统,只写入TPM。如果你想查看,得用工具从TPM里读出来。我一般用tpm2_pcrread命令:
# 读取PCR 8的值
tpm2_pcrread sha256:8
# 读取所有PCR的值
tpm2_pcrread
避坑指南:我曾经遇到过GRUB度量失败的情况,原因是TPM驱动加载太晚。解决方案是在GRUB配置中提前加载tpm模块:在/etc/grub.d/00_header中加入insmod tpm。嗯,这个坑我踩了整整一个下午。
内核度量:IMA的细粒度监控
内核接管系统后,度量进入「深水区」。IMA(Integrity Measurement Architecture)是Linux内核内置的度量框架,它能对文件、进程、甚至内核模块进行细粒度度量。
IMA的工作方式很有意思——它使用「钩子函数」挂载在文件打开、mmap、exec等系统调用上。每次操作发生时,IMA都会计算文件的哈希值,并与预置的「期望值」比对。如果匹配,就记录一条「度量事件」;不匹配?嗯,取决于策略配置,可以只记录,也可以拒绝访问。
IMA的度量策略
IMA策略通过内核参数或sysfs配置。我个人习惯在/etc/ima/ima-policy中定义策略文件:
# 度量所有可执行文件和共享库
measure func=BPRM_CHECK
measure func=FILE_MMAP mask=MAY_EXEC
# 度量关键配置文件
measure func=FILE_CHECK mask=MAY_READ uid=0
# 度量内核模块加载
measure func=MODULE_CHECK
# 度量临时文件(可选,性能开销较大)
# measure func=FILE_CHECK mask=MAY_WRITE
把这个策略加载到内核:
echo "measure func=BPRM_CHECK" > /sys/kernel/security/ima/policy
性能警告:IMA的度量是有性能开销的。我曾经在一个高并发的Web服务器上开启了全量度量,结果CPU使用率直接飙升了15%。建议生产环境只度量关键路径,比如/bin、/usr/bin、/etc等目录。
IMA度量日志的格式
IMA度量日志存储在/sys/kernel/security/ima/ascii_runtime_measurements中。每行记录包含10个字段:
10 1 2c3e50f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f
ima-ng sha256:2c3e50f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f
/boot/vmlinuz-5.10.0-8-amd64
/usr/bin/bash
0x0000000000000000
0x0000000000000000
0x0000000000000000
0x0000000000000000
0x0000000000000000
0x0000000000000000
字段含义:模板名称、哈希算法与值、文件路径、模板特定数据、PCR索引、事件序号、flags、uid、gid、设备号。
说实话,这个日志格式一开始看着挺晕的。我建议你用evmctl工具来解析:
# 查看IMA度量日志摘要
evmctl ima_measurements /sys/kernel/security/ima/ascii_runtime_measurements
# 验证度量日志的完整性
evmctl ima_verify /sys/kernel/security/ima/ascii_runtime_measurements
度量日志解析:从原始数据到可信证据
度量日志是信任链的「证据链」。但原始日志就像一堆乱码,你得知道怎么读。
我总结了一套解析流程:
- 收集基线:在系统「干净」状态下,记录所有度量值。这相当于给系统拍了一张「身份证照片」。
- 实时监控:定期或实时读取度量日志,与基线比对。
- 异常检测:发现不一致时,定位是哪个文件或模块发生了变化。
- 远程证明:将度量日志发送给远程验证服务,由服务端判断系统是否可信。
实用工具:我常用tpm2-tools和ima-evm-utils这两个工具包。前者操作TPM,后者解析IMA日志。安装命令:apt install tpm2-tools ima-evm-utils。
度量日志的完整性验证
度量日志本身也可能被篡改。怎么防?IMA日志的每条记录都包含前一条记录的哈希值,形成了一条「哈希链」。验证方法:
# 从第一条记录开始,逐条验证哈希链
evmctl ima_verify /sys/kernel/security/ima/ascii_runtime_measurements
# 如果输出"Verification successful",说明日志未被篡改
如果验证失败,说明日志被改过。嗯,这时候就该报警了。
知识体系总览
下面这张图展示了启动度量的完整信任链:
从这张图可以看出,信任链是逐级传递的。每一级都依赖上一级的度量结果,最终形成一条完整的证据链。远程证明服务通过比对PCR值和度量日志,就能判断系统是否被篡改过。
总结:启动度量不是一锤子买卖,而是一个持续的过程。从固件到内核,每一层都要「留痕」。这些痕迹最终汇聚成度量日志,成为我们判断系统可信性的依据。记住:没有度量,就没有可信。