12

according to https://wiki.ubuntu.com/UEFI/SecureBoot Initrd images are not validated. Is this information up to date? this would make the whole secure boot totally useless as an attacker could very easily replace initramfs with a one that logs LUKS password and sends it to him... This in turn would make all the module signing hassle and disabling hibernation on secure boot totally ridiculous.

if it's indeed so, is there any launchpad bug/feature-request that we can upvote to make secure boot actually secure?

OTOH, if this statement is obsolete, how does the verification work? where is the key pair that is used to sign initrd files when they are generated during new kernel installations? which component later verifies the signature? (shim, MOK, GRUB, kernel itself?) ...or maybe PCRs and TPM are somehow used instead?
...and how about the kernel command line? this one must be signed/verified also to make the boot secure...

morgwai
  • 261

3 Answers3

13

According to my current understanding with regard to Ubuntu 20.04:

  • shim is signed by Microsoft's key and contains a Canonical key. Microsoft's key is shipped preinstalled in EFI, and is used to validate shim
  • grub is signed by Canonical's key and checked by shim
  • kernel is signed by Canonical's key and checked by grub

There are 2 basic cases:

  1. Attended boot
  • you can encrypt your /boot partition (LUKS1 only, LUKS2 support is not there in Ubuntu 20.04. Newer Grub will support LUKS2 with some limitations (https://git.savannah.gnu.org/cgit/grub.git/tree/docs/grub.texi#n4554)) or have a single system partition with / and /boot (LUKS1)
  • Grub will ask for the password to unlock it and read kernel and initrd from it
    • Note: grub2 is known to be slow (10-20 seconds) to decrypt /boot: I could not find an official acknowledgement of the issue from grub team, but there are many threads on the matter, with workarounds: not using encrypted boot at all or having a key with lower iteration count in the first slot of luks header (ie: https://bbs.archlinux.org/viewtopic.php?id=228865)
  • this way the complete system integrity is protected implicitly by using disk encryption for /boot and /
  1. Unattended boot
  • you can't encrypt /boot in this case, so you have 2 choices
  • sign initrd and kernel and force them to be checked:
    • either you can create an EFI binary with all stuff (kernel, initrd, grub.cfg) packed in it, sign with a custom key and add this key to the EFI key store
    • or do the same thing, but instead of putting everything into the Grub EFI binary, you only add a GPG public key there, which is the one you use to sign the grub.cfg, kernel and initrd (https://ruderich.org/simon/notes/secure-boot-with-grub-and-signed-linux-and-initrd)
    • in either case you'll have to generate signatures or even EFI binaries each time your initrd is updated (ideally automatically via initramfs-tools hooks)
  • if you don't want to mess with signing and have TPM
    • you can leave initrd and /boot as is and let any attacker to modify it, but you bind your root fs to the appropriate TPM registers, effectively preventing access to the rootfs if anybody has altered kernel parameters, any used files (kernel binary, initrd, grub.cfg)...
    • the only drawback here is, that after initrd/kernel change, you'll have to do a reboot, manually unlock the disk and rebind the TPM bound key slot on LUKS to the new PCR register values and make sure, that during this reboot nobody altered any of the /boot content. Ideal solution would be if one could calculate the future TPM value and as such not have to keep luks TPM bound. A project which is addressing this issue: https://github.com/grawity/tpm_futurepcr

Some further assorted references:

Update: 2022-11-07: added some sources and details on grub2 limitations

2

You do not even need to sign/verify the initramfs, because you do not need to keep it accessible (unenencrypted on a local disk).

Ubuntu 20.04 is perfectly capable of dealing with an installation layout where the initrd file is contained inside an encrypted container (currently works for luks1 on AMD64 & ARM64, luks2 and more platforms in future versions). Other than downgrading to the earliest version with identical kernel, nobody but you could modify the initrd sealed with your password.

The part that is really missing in current automation is the generation of a signed grub binary that verifies its own configuration. It works out of the box too - grub can verify gpg-style signatures - but the kernel install scripts shipped by Canonical do not setup/update that in the usual fully automatic fashion.

If you wanted to to configure a fully verified boot chain in current Ubuntu releases, you might try to place your own script (which gpg --signs your config, then integrates that into the grub binary using grub-mkstandalone then sbsigns that binary before placing it into /boot/efi) into /etc/kernel/postinst.d/ to have it automatically called whenever your install/remove a kernel (version).

Note that almost no consumer PC is actually used to enroll custom keys for secure boot (MOK), so you will likely run into some firmware bugs. You will not find too many bug reports about this topic either, simply because few people want/do such a complicated and error-prone thing.

And this is just the Ubuntu side of things. You probably win nothing in terms of security (but you are welcome to contribute there).

anx
  • 2,457
  • 2
  • 26
  • 38
0

You might need to define a threat model first: what are you trying to protect against?

Secure Boot should prevent even the root user from breaking the integrity of code that runs at kernel-level privilege. This is most obvious at boot: even root should not be able to install a kernel or bootloader that isn't trustworthy, and we use signatures to determine trustworthiness. However, it also extends to the running kernel: Ubuntu kernels will detect secure-boot and enter lockdown integrity mode early in boot. Integrity mode attempts to maintain that security boundary between root and the kernel at runtime. (This stops you doing something like kexec-ing from a trusted kernel to an untrusted one.)

Something that has never been part of the secure boot mission is protecting against root replacing non-kernel binaries. This is a reasonably difficult problem and scripting languages make it even harder. It's even more fraught in the FOSS world because people get very irate at anything they perceive to be limiting software freedom, even if it's possible to disable. (See, for example, what Apple does with signing basically everything!)

There are definitely ways to restrict root installing malicious binaries. You can use grub's detached signature support to require that the initrd is signed. But then everything, even grub.cfg, has to be signed, and that would get really irritating to administer. You could use something like dm-verity. IMA could help you (but not so much for scripts). But you very quickly stop having a general purpose system!

dja
  • 711