第 7 章:加密与认证
第 7 章:加密与认证
7.1 GRUB 安全概述
GRUB2 提供了多层安全机制,防止未授权用户篡改引导参数或进入救援模式。这对于服务器、公共终端和安全敏感环境尤为重要。
安全层级
┌─────────────────────────────────────────┐
│ 层级 1: 保护编辑引导参数 │ ← 防止修改内核命令行
│ 用户不能按 'e' 编辑菜单项 │
├─────────────────────────────────────────┤
│ 层级 2: 保护 GRUB Shell │ ← 防止进入命令行
│ 用户不能按 'c' 进入 Shell │
├─────────────────────────────────────────┤
│ 层级 3: 保护特定菜单项 │ ← 敏感操作需要密码
│ 救援模式等需要认证 │
├─────────────────────────────────────────┤
│ 层级 4: 保护整个菜单 │ ← 所有操作需要密码
│ 任何选择都需要认证 │
└─────────────────────────────────────────┘
7.2 密码保护
7.2.1 生成密码哈希
方式一:grub-mkpasswd-pbkdf2(推荐)
# 交互式生成密码哈希
$ grub-mkpasswd-pbkdf2
Enter password: <输入密码>
Reenter password: <再次输入>
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
方式二:在脚本中生成
# 非交互式生成(用于自动化脚本)
$ echo -e "mypassword\nmypassword" | grub-mkpasswd-pbkdf2 | grep "PBKDF2" | awk '{print $NF}'
7.2.2 设置超级用户密码
编辑 /etc/grub.d/40_custom(或 00_header,取决于发行版):
# /etc/grub.d/40_custom 文件开头添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF
# 以下为自定义菜单项
menuentry "..." {
...
}
或在 /etc/grub.d/00_header 末尾(update-grub 前需手动编辑):
# 在 00_header 的末尾,exec tail 行之前添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF
7.2.3 配置级别保护
级别 1:仅保护编辑功能
# 用户不能编辑菜单项(按 e),但可以直接启动
# 在 /etc/grub.d/40_custom 中添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF
级别 2:保护编辑和 Shell,但允许无密码启动
# 菜单项使用 --unrestricted 标记允许无密码启动
menuentry "Normal Boot" --unrestricted {
linux /boot/vmlinuz root=UUID=xxx ro quiet
initrd /boot/initrd.img
}
# 受限菜单项需要密码
menuentry "Recovery Mode" {
linux /boot/vmlinuz root=UUID=xxx ro single
initrd /boot/initrd.img
}
级别 3:所有菜单项需要密码
# 不使用 --unrestricted,且设置 superusers
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
# 此时所有 menuentry 默认需要密码
# 可以通过 --unrestricted 例外
7.2.4 menuentry 选项与密码的关系
| 选项 | 无 superusers | 有 superusers |
|---|---|---|
| (无选项) | 所有人可启动 | 需要密码 |
--unrestricted | 所有人可启动 | 所有人可启动 |
--users "" | 所有人可启动 | 所有人可启动 |
--users admin | 所有人可启动 | 仅 admin 可启动 |
7.2.5 多用户配置
# 设置多个超级用户
set superusers="admin root"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...
password_pbkdf2 root grub.pbkdf2.sha512.10000.YYY...
# 普通用户(非超级用户)只能看到 unrestricted 项
password_pbkdf2 guest grub.pbkdf2.sha512.10000.ZZZ...
# 管理员专用菜单项
menuentry "Admin Tools" --users admin {
...
}
# 所有人可用的菜单项
menuentry "Normal Boot" --unrestricted {
...
}
7.3 认证机制详解
7.3.1 用户认证流程
用户选择菜单项
│
▼
该菜单项是否需要认证?──── 否 ──→ 直接启动
│
是
▼
提示输入用户名和密码
│
▼
认证是否成功?──── 是 ──→ 启动菜单项
│
否
▼
显示错误,返回菜单
7.3.2 认证配置位置
认证配置应放在 grub.cfg 的菜单定义之前。通常在 40_custom 中添加:
#!/bin/sh
exec tail -n +3 $0
# 认证配置
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...
# 以下为菜单项
menuentry "..." { ... }
7.4 LUKS 加密分区引导
7.4.1 LUKS 概述
LUKS(Linux Unified Key Setup)是 Linux 的标准磁盘加密方案。GRUB2 可以在引导阶段解密 LUKS 加密分区,实现完整的加密启动链。
7.4.2 安装支持 LUKS 的 GRUB
# Debian/Ubuntu
$ sudo apt install grub-pc # BIOS(默认包含 cryptodisk 模块)
# 或
$ sudo apt install grub-efi-amd64
# 确认 cryptodisk 模块存在
$ ls /boot/grub/*/cryptodisk.mod
# /boot/grub/x86_64-efi/cryptodisk.mod
# /boot/grub/i386-pc/cryptodisk.mod
7.4.3 配置 GRUB 支持加密分区
编辑 /etc/default/grub:
# 启用 cryptodisk 支持
GRUB_ENABLE_CRYPTODISK=y
重新生成配置:
$ sudo update-grub
7.4.4 LUKS1 vs LUKS2
| 特性 | LUKS1 | LUKS2 |
|---|---|---|
| GRUB 支持 | ✅ 2.06+ | ✅ 2.06+(部分) |
| 默认 | 老版本默认 | 新版本默认 |
| PBKDF | PBKDF2 | Argon2id |
| 元数据 | 固定位置 | JSON 格式,灵活 |
| 推荐 | 最大兼容性 | 新系统推荐 |
⚠️ 注意:GRUB 对 LUKS2 的支持有限,特别是 Argon2id KDF 可能不被支持。为最大兼容性,建议对
/boot分区使用 LUKS1,或使用标准 PBKDF2 而非 Argon2id。
7.4.5 完整加密引导配置示例
场景:根分区使用 LUKS 加密,/boot 在加密分区内。
# /etc/default/grub
GRUB_CMDLINE_LINUX="cryptdevice=UUID=xxxx:myroot"
GRUB_ENABLE_CRYPTODISK=y
启动流程:
GRUB 加载 → 提示输入 LUKS 密码 → 解密分区
→ 加载内核和 initramfs → 内核启动 → 再次提示密码(或使用 keyfile)
⚠️ 注意:使用 LUKS 加密时,GRUB 启动阶段会提示输入一次密码,进入 initramfs 后可能再次提示。要避免双重密码提示,需要在 initramfs 中配置 keyfile 或使用 TPM。
7.4.6 分离 /boot 分区方案
为简化加密引导,常见做法是将 /boot 放在未加密分区:
/dev/sda1 → /boot/efi (FAT32, 512MB, 未加密)
/dev/sda2 → /boot (ext4, 1GB, 未加密)
/dev/sda3 → / (ext4, LUKS 加密)
这种方案下 GRUB 不需要 cryptodisk 模块,密码提示只在 initramfs 阶段出现一次。
7.5 安全启动链
完整的安全启动链应该包含:
UEFI Secure Boot
→ shim (Microsoft 签名)
→ GRUB (发行版签名)
→ 内核 (发行版签名)
→ initramfs
→ dm-verity / IMA
每个环节都验证下一环节的签名,形成信任链。
7.6 防止未授权修改
7.6.1 保护 GRUB 配置文件
# 限制 grub.cfg 的访问权限
$ sudo chmod 600 /boot/grub/grub.cfg
$ sudo chown root:root /boot/grub/grub.cfg
# 保护 grubenv
$ sudo chmod 600 /boot/grub/grubenv
7.6.2 保护 /etc/default/grub
$ sudo chmod 644 /etc/default/grub
$ sudo chown root:root /etc/default/grub
7.6.3 物理安全
即使配置了密码保护,攻击者仍可通过以下方式绕过:
- 从其他介质(USB)引导
- 修改 BIOS/UEFI 设置从其他设备引导
- 拔出硬盘直接读取数据
防护措施:
- 设置 BIOS/UEFI 密码
- 禁用从外部设备引导
- 使用 Secure Boot
- 加密磁盘(LUKS)
7.7 完整安全配置示例
# /etc/grub.d/40_custom 完整安全配置
#!/bin/sh
exec tail -n +3 $0
# ===========================
# 认证配置
# ===========================
# 超级用户(可以编辑和使用 Shell)
set superusers="admin"
# 超级用户密码(PBKDF2 哈希)
password_pbkdf2 admin grub.pbkdf2.sha512.10000.CC1D9C56B6F8A9E2...(实际哈希很长)
# ===========================
# 正常启动(所有人可用)
# ===========================
menuentry "Debian GNU/Linux" --unrestricted {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root XXXX-XXXX
linux /boot/vmlinuz root=UUID=XXXX ro quiet
initrd /boot/initrd.img
}
# ===========================
# 恢复模式(需要管理员密码)
# ===========================
menuentry "Debian GNU/Linux (Recovery)" --users admin {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root XXXX-XXXX
linux /boot/vmlinuz root=UUID=XXXX ro single
initrd /boot/initrd.img
}
# ===========================
# UEFI 设置入口(需要管理员密码)
# ===========================
menuentry "UEFI Firmware Settings" --users admin {
fwsetup
}
7.8 密码管理
7.8.1 更换密码
# 生成新密码哈希
$ grub-mkpasswd-pbkdf2
Enter password: <新密码>
Reenter password: <确认>
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.NEW_HASH...
# 更新 /etc/grub.d/40_custom 中的哈希值
$ sudo nano /etc/grub.d/40_custom
# 替换 password_pbkdf2 行中的哈希
# 重新生成配置
$ sudo update-grub
7.8.2 忘记密码的恢复
# 从 Live USB 引导后
$ sudo mount /dev/sda2 /mnt
$ sudo nano /mnt/etc/grub.d/40_custom
# 注释掉或删除 password_pbkdf2 行和 set superusers 行
$ sudo mount /dev/sda1 /mnt/boot/efi
$ sudo mount --bind /dev /mnt/dev
$ sudo mount --bind /proc /mnt/proc
$ sudo mount --bind /sys /mnt/sys
$ sudo chroot /mnt
# update-grub
# exit
7.9 安全审计
7.9.1 检查当前安全状态
# 检查是否设置了密码保护
$ grep -n "superusers\|password_pbkdf2" /etc/grub.d/40_custom
# 检查 grub.cfg 中的认证配置
$ grep -n "superusers\|password" /boot/grub/grub.cfg
# 检查 Secure Boot 状态
$ mokutil --sb-state
# SecureBoot enabled
# 检查加密磁盘状态
$ sudo cryptsetup status /dev/mapper/myroot
7.9.2 安全检查清单
| 检查项 | 命令 | 预期 |
|---|---|---|
| 密码保护已启用 | grep superusers /boot/grub/grub.cfg | 有 set superusers= |
| PBKDF2 密码已设置 | grep password_pbkdf2 /boot/grub/grub.cfg | 有 password_pbkdf2 |
| Secure Boot 已启用 | mokutil --sb-state | SecureBoot enabled |
| BIOS 密码已设置 | 重启进入 BIOS 检查 | 需要密码才能修改 |
| 磁盘已加密 | lsblk -f | LUKS 分区存在 |
| 配置文件权限 | ls -l /boot/grub/grub.cfg | -rw------- root root |
7.10 扩展阅读
上一章:第 6 章:主题与美化 | 下一章:第 8 章:恢复模式