4. BootLoader 安全:GRUB2 安全配置、引导加载程序签名验证、内核完整性度量、initramfs 保护

BootLoader 是可信启动链的第一环。说白了,它负责把内核从磁盘请进内存。如果这一环被攻破,后面再怎么加固都是白搭。我见过太多团队花大价钱做内核加固,结果 GRUB 连个密码都没设——攻击者直接改启动参数进单用户模式,整个系统就像没锁门一样。

这一章我们聚焦四个核心点:GRUB2 的安全配置、引导加载程序的签名验证、内核完整性度量,以及 initramfs 的保护。每个点我都会结合项目中的实际踩坑经历来讲。

4.1 GRUB2 安全配置:别让大门敞着

GRUB2 是 Linux 世界最主流的引导加载程序。默认配置下,它没有任何访问控制。你想想看,只要物理接触机器,按个 e 键就能改启动参数,加个 init=/bin/bash 直接拿 root shell——这跟没锁门有什么区别?

4.1.1 设置 GRUB 密码

第一步,给 GRUB 加个密码。我习惯用 PBKDF2 哈希,别用明文密码。

# 生成 PBKDF2 哈希密码
grub-mkpasswd-pbkdf2
# 输入密码后得到一串哈希,类似:
grub.pbkdf2.sha512.10000.ABCDEF...

# 编辑 /etc/grub.d/40_custom
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.ABCDEF...

# 更新 GRUB 配置
grub2-mkconfig -o /boot/grub2/grub.cfg
注意: 设置 superusers 后,所有菜单项默认都需要认证。如果你只想保护编辑功能,可以单独配置 --unrestricted 参数。我曾经见过有人设了密码但忘了加 superusers,结果密码根本没生效——白忙活一场。

4.1.2 禁用交互式编辑

光有密码还不够。攻击者如果拿到物理机,可以进 GRUB 救援模式。我建议把以下配置加到 /etc/default/grub:

GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE=menu
GRUB_DISABLE_RECOVERY="true"
GRUB_CMDLINE_LINUX="quiet splash lockdown=confidentiality"

lockdown=confidentiality 这个参数很多人不知道。它能在内核层面禁用 kexec、休眠、调试接口等危险功能。嗯,这个是我在给某金融机构做等保测评时学到的。

4.2 引导加载程序签名验证:UEFI Secure Boot 实战

GRUB 密码防的是本地用户,但防不了恶意软件改写引导扇区。这时候就需要 UEFI Secure Boot 出场了。

Secure Boot 的原理很简单:UEFI 固件只加载由可信证书签名的 EFI 程序。从固件到 GRUB,再到内核,形成一条签名链。

核心概念: Secure Boot 不是 GRUB 的功能,而是 UEFI 固件的特性。GRUB 需要被签名,并且要支持 shim 协议才能正常工作。

4.2.1 签名流程

我建议用 Machine Owner Key (MOK) 来管理自己的签名密钥。流程如下:

  1. 生成自己的签名密钥对
  2. 用私钥签名 GRUB EFI 文件
  3. 将公钥注册到 MOK 数据库
  4. 重启后通过 MOK 管理界面确认
# 生成密钥
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.key \
  -out MOK.crt -days 3650 -nodes -subj "/CN=My Secure Boot Key/"

# 签名 GRUB
sbsign --key MOK.key --cert MOK.crt \
  --output /boot/efi/EFI/centos/grubx64.efi \
  /boot/efi/EFI/centos/grubx64.efi

# 注册公钥到 MOK
mokutil --import MOK.crt
经验之谈: 签名前一定要备份原始 GRUB EFI 文件。我遇到过签名后 GRUB 无法启动的情况,原因是对齐问题。用 sbverify --list /boot/efi/EFI/centos/grubx64.efi 可以验证签名是否生效。

4.3 内核完整性度量:IMA 与 LSM 的配合

签名验证保证的是启动时内核文件没被篡改。但运行时呢?内核模块加载、关键文件访问,这些都需要持续度量。这就是 Integrity Measurement Architecture (IMA) 的用武之地。

IMA 是 Linux 内核的一个安全子系统。它会在文件被访问时计算哈希,并与预存的度量值比对。说白了,就是给系统装了个「文件完整性监控器」。

4.3.1 IMA 配置要点

启用 IMA 需要内核编译时开启 CONFIG_IMA,并在启动参数中加入:

ima_appraise=fix ima_hash=sha256 ima_policy=tcb

这里有个坑:ima_appraise=fix 是修复模式,它会自动更新度量值。生产环境一定要用 ima_appraise=enforce,否则 IMA 只记录不阻止——等于没开。

IMA 模式 行为 适用场景
enforce 阻止未度量文件访问 生产环境
fix 自动更新度量值 初始部署/调试
log 仅记录不阻止 审计评估

我建议配合 EVM (Extended Verification Module) 一起使用。EVM 能保护 IMA 度量值的完整性,防止攻击者篡改度量数据库。

4.4 initramfs 保护:被忽视的薄弱环节

initramfs 是内核启动早期加载的临时根文件系统。它包含驱动、脚本和必要的工具。很多人只关注内核和 GRUB,却忘了 initramfs 同样可以被篡改。

攻击者如果替换了 initramfs 中的脚本,就能在系统完全启动前植入后门。我曾在一次红蓝对抗中,通过修改 initramfs 里的 init 脚本,成功绕过了所有磁盘加密——因为解密脚本本身就在 initramfs 里。

4.4.1 签名与加密 initramfs

保护 initramfs 有两个层面:

  1. 签名验证: 确保 initramfs 文件未被篡改
  2. 加密存储: 防止敏感信息(如解密密钥)泄露
# 使用 dracut 生成签名 initramfs
dracut --force --verify --sign \
  --key /path/to/private.key \
  --cert /path/to/cert.pem \
  /boot/initramfs-$(uname -r).img $(uname -r)

# 验证签名
dracut --verify /boot/initramfs-$(uname -r).img
重要: 签名密钥必须与 GRUB 或内核度量使用的密钥分开管理。我曾经见过有人把所有签名用同一个密钥,结果一个泄露全盘皆输。密钥隔离是基本的安全原则。

4.4.2 最小化 initramfs 内容

另一个容易被忽视的点:initramfs 里不要放多余的东西。默认生成的 initramfs 包含大量驱动,很多你根本用不上。我习惯用 dracut --omit-drivers 排除不必要的模块:

# 只保留必要驱动
dracut --force --omit-drivers "floppy pata_acpi ata_piix" \
  --add-drivers "nvme ext4" \
  /boot/initramfs-$(uname -r).img $(uname -r)

这样做的好处是:攻击面缩小了,启动速度也快了。嗯,一举两得。

4.5 本章知识体系总览

下面这张图把 BootLoader 安全的四个维度串起来了。你可以看到,从 UEFI 固件到内核启动,每一层都有对应的保护措施。

BootLoader 安全防御体系 BootLoader 安全防御体系 UEFI 固件层 Secure Boot 签名验证 · 平台密钥 (PK) · 密钥交换密钥 (KEK) GRUB2 引导加载程序 密码保护 · 菜单锁定 · 启动参数限制 · shim 签名链 内核 + initramfs IMA 完整性度量 · EVM 扩展验证 · initramfs 签名与加密 运行时安全 LSM 强制访问控制 · 内核模块签名 · 运行时度量持续验证 ⚠ 每一层都需要独立保护 单点失效不会导致全链崩溃 🔑 密钥管理是关键 各层密钥隔离,定期轮换

从这张图可以看得很清楚:可信启动链不是单点防御,而是层层递进的纵深体系。UEFI 固件负责硬件级签名验证,GRUB 提供用户态访问控制,IMA 做运行时完整性度量,initramfs 保护早期启动环境。每一层都不可或缺。

我的建议: 别想着一步到位。先从 GRUB 密码和 Secure Boot 做起,这两项投入产出比最高。等基础打牢了,再上 IMA 和 initramfs 加密。我在多个项目里都是这么推的,效果不错。