4、UEFI安全启动:UEFI Secure Boot原理、PK/KEK/db/dbx数据库、签名与验证流程
UEFI Secure Boot,说白了就是给电脑的启动过程加了一把锁。我刚开始接触这个功能时,觉得它就是个麻烦——动不动就把系统搞黑屏。后来在几个安全合规项目里被折腾过几次,才真正理解了它的价值。
它的核心逻辑其实很简单:只允许运行经过签名的、可信的代码。从固件到引导加载器,再到操作系统内核,每一环都要验明正身。任何一个环节出了问题,启动就会中断。
4.1 核心数据库:PK、KEK、db、dbx
这四个数据库是Secure Boot的命根子。它们存储在主板上的NVRAM里,跟BIOS设置是分开的。我见过不少运维同事误以为清BIOS就能重置Secure Boot,结果发现根本没用——因为这些数据是独立存储的。
| 数据库 | 全称 | 作用 | 数量 |
|---|---|---|---|
| PK | Platform Key | 平台密钥,最高权限 | 通常1个 |
| KEK | Key Exchange Key | 密钥交换密钥,管理db/dbx | 可多个 |
| db | Signature Database | 白名单,允许执行的签名 | 可多个 |
| dbx | Forbidden Signature Database | 黑名单,禁止执行的签名 | 可多个 |
PK(平台密钥)是老大。它只用来签名KEK的更新。一旦PK被清空或设置为空,Secure Boot就自动进入"设置模式",这时候任何人都可以修改数据库。嗯,这里要注意——很多主板出厂时PK是空的,这就是为什么你买的新电脑默认能装各种系统。
KEK(密钥交换密钥)是管家。它负责签名db和dbx的更新。微软的KEK几乎在所有支持Windows的机器上都存在。我个人习惯在部署Linux时保留微软的KEK,这样万一要双系统启动,不会出问题。
db(签名数据库)是白名单。里面存的是允许执行的签名证书或文件的哈希值。比如微软的Windows引导加载器签名就在这里面。我在项目中遇到过有人误删了db里的微软证书,结果Windows直接启动不了——那叫一个尴尬。
dbx(禁止签名数据库)是黑名单。用来吊销有安全漏洞的引导加载器签名。比如2018年的BootHole漏洞,就是通过更新dbx来封堵的。你想想看,如果没有这个机制,一个被攻破的引导加载器可以一直用下去,那多可怕。
4.2 签名与验证流程
整个验证流程是一个链式结构。我画了一张图帮你理解:
验证流程其实就三步:
- 固件启动:UEFI固件先检查Boot Manager的签名是否在db里,且不在dbx里。如果通过,就加载它。
- 链式传递:Boot Manager再去验证下一个要加载的程序(比如shim或GRUB)的签名。每一环都用自己的签名证书去验下一环。
- 内核加载:最后引导加载器验证操作系统内核的签名。全部通过,系统才能正常启动。
关键点:整个链条上任何一个环节的签名验证失败,启动就会停止。屏幕上通常会显示"Secure Boot Violation"之类的错误信息。
4.3 实际操作中的避坑指南
我在生产环境里踩过不少坑,挑几个典型的说说:
坑1:自己签名的内核启动不了
我曾经自己编译了一个内核,用自己的证书签了名,结果死活启动不了。查了半天才发现——我的证书虽然加到了db里,但签名算法用的是SHA-1,而固件只支持SHA-256。后来换了算法就OK了。
教训:签名前先查一下固件支持的哈希算法,别想当然。
技巧:查看当前Secure Boot状态
在Linux下可以用这个命令:
# 查看Secure Boot是否启用
mokutil --sb-state
# 查看当前db里的证书列表
mokutil --list-enrolled
# 查看dbx里的黑名单
mokutil --list-blacklist
坑2:更新固件后Secure Boot失效
有一次我给服务器更新了BIOS,重启后系统直接进了恢复模式。一查发现Secure Boot被重置成了"设置模式",所有自定义证书都没了。原来那个固件更新把NVRAM给清空了。
教训:更新固件前,先用efibootmgr导出当前的Secure Boot配置。更新完再导回去。
4.4 签名工具与操作示例
实际操作中,最常用的工具是sbsigntool和sign-efi-sig-list。我一般这么用:
# 1. 生成自己的签名证书
openssl req -new -x509 -newkey rsa:2048 -keyout my.key \
-out my.crt -days 3650 -subj "/CN=My Secure Boot Key/"
# 2. 用证书签名EFI文件
sbsign --key my.key --cert my.crt --output /boot/efi/EFI/BOOT/grubx64.efi.signed \
/boot/efi/EFI/BOOT/grubx64.efi
# 3. 将证书导入到db数据库
mokutil --import my.crt
# 4. 重启后按提示完成证书注册
reboot
这里有个细节——mokutil导入证书后,重启时会进入MOK管理界面,需要手动确认。我第一次用的时候不知道,重启后傻等了半天,以为系统卡死了。其实只要按几个键确认就行。
4.5 关于shim的补充说明
说到Linux下的Secure Boot,就绕不开shim。它是一个微小的引导加载器,由微软签名,然后用来加载GRUB。为什么要多这一层?因为GRUB的签名证书变更比较频繁,每次变更都要找微软签名太麻烦。shim的证书相对稳定,用它来验GRUB就灵活多了。
我在项目中遇到过shim版本不匹配的问题。比如系统里装的是shim 15.4,但GRUB是15.6编译的,结果shim验GRUB签名时失败。解决办法就是保持shim和GRUB版本一致,或者用sbverify先检查一下签名是否匹配:
# 检查GRUB的签名是否被shim的证书验证
sbverify --cert /usr/share/shim/shim.cer /boot/efi/EFI/centos/grubx64.efi
一句话总结:Secure Boot就是个信任链,从固件到内核,每一环都要验明正身。PK是根信任,KEK管更新,db/dbx管执行权限。配置时注意算法兼容性,更新固件前记得备份配置。
可可精品资料库