Attempting to get secure boot and bootable BTRFS snapshots

linux
cybersecurity
_playground
Published

August 29, 2023

If these steps are followed blindly, you risk compromising your security

Do not do what I did unless you have a similar setup to what I have, which is full disk encryption, with /boot/efi being the efi system partition, and the only unencrypted part of the system. This means that everything in /boot, including things like kernels, or grub configurations and supportive files.

I’ve been at this for some time now, so I will document what I have done, and further steps. Essentially, I am trying to do what this person archive has done.

They go more into depth on the setup that we are both using, but essentially, I the only unencrypted part of my system is the grub efi binary. Normally, the kernels and kernel modules are also left unencrypted, and because of that, they must be signed in order to prevent an attacker from modifying them on the hard drive, either by removing the hard drive, or booting another operating system, like by a USB drive. Signing is a process that uses complex math to ensure that the computer can verify the authenticity of a file.

Normally, since the kernels are left unencrypted (and to cut off another avenue of attack on running systems), the kernels are signed in order to ensure that they haven’t been modified. However, in my setup, since only grub is left unencrypted, it’s the only thing that can be signed.

But for some reason, grub still attempts to verify the kernels even when it doesn’t need to. This is my struggle of getting it to not do that.

The first thing I did sign grub. I followed the insturctions on the Arch Wiki. Except, rather than signing the kernels, I only signed grub.

I enabled secure boot, and reboted. Grub loaded up, and asked me for my password, but then gave me an error and put me into a rescue shell.

error: prohibited by secure boot policy

So I did some searching around. I found someone with the same issue on the Arch Linux BBS. On that page, someone (reply #4) said that an update of grub (grub version 2.06, to be specific) had a change in policy where grub would refuse to load unsigned font files when in secure mode. This is good. There have been CVE’s (security vulnerabilities/issues) in the past where grub loading a malicious grub.cfg or font file can be exploited to make grub do things it’s not supposed to.

Except one tiny problem: Grub stores all configuration and font files in /boot/grub, which is encrypted in my setup. An attacker would not be able to modify it, so therefore I have no need to verify it. It’s actually a hassle to verify all this stuff, because they are tracked by BTRFS, and will be restored.

After some more research, I decided to install grub with the shim-lock option.

But I got another error:

error: verification requested, but nobody cares: (cryptouid:uidhere/boot/grub/x86_64-efi/normal.mod)

Normal mod was not signed.

Apparently, as long as secure boot it enabled, grub still attempts to verify the files. I did some searching around, before finding this article, which I also linked above. They used sed (text finder and replacer) to replace some things in the grub binary.

sed 's/SecureBoot/SecureB00t' grubx64.efi

Except, after I ran this command:

[root@lizard boot]# sbctl verify
Verifying file database and EFI images in /boot/efi...
✓ /boot/efi/EFI/cachyos/grubx64.efi is signed

The grub binary stayed signed. Even after modification. What? Shouldn’t the grub binary being modified, break the signatures? Unless it does (I haven’t rebooted yet), and it’s just that the the sbctl tool doesn’t check whether or not the signatures are valid.

Regardless, I can’t know until I test, and I didn’t bother. I simmply resigned the the grub binary, but it still didn’t work.

I forgot to install grub with the --disable-shim-lock option.

Before this, I nuked the /boot/efi directory to ensure that nothing extraneous was left. For some reason, cachyos (arch based distro I am using), installs grub twice, once at /boot/efi/EFI/boot and another at /boot/efi/EFI/cachyos. Having only one grub binary further simplifies this process.

So my full steps would be (requires root):

grub-install --target=x86_64-efi --efi-directory=/boot/efi --disable-shim-lock
sed -i 's/boot/efi/EFI/cachyos/' grubx64.efi

An unorthodox grub hack, but it works.

If a grub update ever breaks this, or maybe just to futureproof this, then I’ll probably just use Arch’s PKGBUILD, makepkg, and patch tools to patch the grub_efi_get_secureboot function of sb.c so that grub always thinks it’s not in secure boot. I think I would only need to change one line, return secureboot, or maybe reset the variable to what I want at the end of the function, but I’m not too familier with C code at the moment. I can read it, given context, but I’ve not written it yet.