
0) Threat model (why this matters)
If an attacker can edit the GRUB menu or inject parameters via PXE/provisioning, they can poke early-boot code paths (like IOMMU parsing). We:
- lock GRUB; 2) enforce Secure Boot + kernel lockdown; 3) lock provisioning paths; 4) remove alternate boot vectors.
1) Enable & verify Secure Boot (+ Lockdown)
Check status (any distro):
mokutil --sb-state # expect: SecureBoot enabled
cat /sys/kernel/security/lockdown # expect: "integrity" or "confidentiality" (read-only)
If disabled: enable in firmware (UEFI Setup) → “Secure Boot: Enabled”.
Custom modules: if you use DKMS/custom drivers, sign them or use a Unified Kernel Image (UKI) workflow; avoid enrolling overly broad MOKs.
Optional stricter lockdown: add lockdown=confidentiality to your kernel cmdline (once GRUB is password-protected).
2) Protect GRUB (set superuser + hashed password)
Generate a PBKDF2 hash:
sudo grub-mkpasswd-pbkdf2
# paste the 'grub.pbkdf2.sha512....' hash
Add a GRUB superuser (GRUB2):
sudo tee -a /etc/grub.d/40_custom >/dev/null <<'EOF'
set superusers="grubadmin"
password_pbkdf2 grubadmin grub.pbkdf2.sha512.10000.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
EOF
Require auth to edit/select entries: (Ubuntu/Debian)
sudo sed -i 's/^#\?GRUB_TIMEOUT_STYLE=.*/GRUB_TIMEOUT_STYLE=hidden/' /etc/default/grub
sudo sed -i 's/^#\?GRUB_TIMEOUT=.*/GRUB_TIMEOUT=0/' /etc/default/grub
sudo update-grub
RHEL/Alma/SUSE (GRUB cfg regeneration):
# BIOS:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# UEFI:
sudo grub2-mkconfig -o /boot/efi/EFI/$(ls /boot/efi/EFI | head -n1)/grub.cfg
Use when you need the menu:
# one-time next boot to a menu entry (no interactive editing needed)
sudo grub-reboot 1 && sudo reboot
Tip: Keep a sealed, offline copy of the hash and a break-glass bootable USB.
3) Lock file permissions & restrict boot devices
# GRUB & /boot must be root-only
sudo chown -R root:root /boot /etc/grub.d
sudo chmod -R go-rwx /etc/grub.d
sudo chmod 600 /boot/grub*/grub.cfg 2>/dev/null || true
# Remove unused boot entries (USB, CD) at firmware level
# Set UEFI BootOrder to disk only; disable "Boot from USB" unless needed.
4) Disable kexec (no in-OS kernel swapping)
echo "kernel.kexec_load_disabled=1" | sudo tee /etc/sysctl.d/99-hardening.conf
sudo sysctl --system
5) Harden PXE / provisioning (if used)
- Disable PXE where not required; otherwise:
- Use UEFI Secure Boot-signed iPXE or vendor-signed boot loaders only.
- Serve boot artifacts over HTTPS with certificate pinning; avoid unauthenticated TFTP.
- Isolate provisioning on a dedicated VLAN, DHCP-scoped to known MACs.
- Store kernel/initrd on a read-only web root with CI-signed artifacts.
- Require change-control to modify kernel parameters in your provisioning templates.
6) Baseline & monitor
# Record a golden cmdline
cat /proc/cmdline | sudo tee /etc/cmdline.baseline
# Simple drift check (put in a cron/systemd timer)
if ! diff -q /etc/cmdline.baseline /proc/cmdline >/dev/null; then
logger -p authpriv.alert "CMDLINE DRIFT DETECTED: $(cat /proc/cmdline)"
fi
7) Recovery plan (don’t lock yourself out)
- Keep UEFI admin password in a sealed secret manager (two-person rule).
- Maintain a signed rescue image (USB) you can boot when GRUB is protected.
- Document the grubadmin password reset workflow.
Drop-in repo file
Add this to your repo as HARDENING.md, and include a helper script:
scripts/grub_harden.sh
#!/usr/bin/env bash
set -euo pipefail
HASH="${1:-}" # pass the grub PBKDF2 hash as $1
[ -z "$HASH" ] && { echo "Usage: $0 <grub.pbkdf2.hash>"; exit 1; }
sudo tee -a /etc/grub.d/40_custom >/dev/null <<EOF
set superusers="grubadmin"
password_pbkdf2 grubadmin $HASH
EOF
if command -v update-grub >/dev/null; then
sudo sed -i 's/^#\?GRUB_TIMEOUT_STYLE=.*/GRUB_TIMEOUT_STYLE=hidden/' /etc/default/grub
sudo sed -i 's/^#\?GRUB_TIMEOUT=.*/GRUB_TIMEOUT=0/' /etc/default/grub
sudo update-grub
else
sudo grub2-mkconfig -o /boot/grub2/grub.cfg 2>/dev/null || true
VENDOR=$(ls /boot/efi/EFI | head -n1 || echo "")
[ -n "$VENDOR" ] && sudo grub2-mkconfig -o "/boot/efi/EFI/$VENDOR/grub.cfg"
fi
sudo chown -R root:root /boot /etc/grub.d
sudo chmod -R go-rwx /etc/grub.d
sudo chmod 600 /boot/grub*/grub.cfg 2>/dev/null || true
echo "[OK] GRUB hardened."
Leave a comment