Definitions
Grub
is the second stage bootloader often found in Linux distributions.
shim
is the first bootloader ran by the ROM firmware. It is signed by Microsoft.
ROM firmware
is the code embedded in the hardware which implements the UEFI standard. It used to be called BIOS but after UEFI was introduced that isn't technically correct any more.
How does the secure boot chain of trust work?
ROM firmware
comes with the Microsoft1 key embedded by default. It confirms that shim
is correctly signed and loads shim
.
shim
has the Debian2 keys and will confirm that grub
is signed and if so it will load grub
.
grub
has a module which will use the API from shim
to check if the kernel is signed with the Debian keys. If so it will load it.
The kernel then loads userspace, but UEFI secure boot doesn't really care from there on.
So what's the problem?
Grub is scriptable and those scripts aren't being verified as part of secure boot. Grub offers a mechanism to verify external files but it's a mechanism which doesn't use the keys from shim
and is unrelated to secure boot.
So secure boot with grub won't check the signature of the script. It will execute any malicious code even if all the components before and after are checked for the correct signature.
However, secure boot implementation in grub will prevent any unsigned kernel to be loaded. This way it prevented loading of malicious code but allowed for the possibility of bricking the device.
Question
Is this a security flaw in grub's implementation of secure boot or are the limits of what secure boot just defined like that and other bootloaders behave the same?
[1] - You can also embed other keys into the firmware directly if that makes sense for your case. You don't need shim then, but grub won't know how to reuse this
[2] - I'm assuming here Debian is the distro. The Debian keys get embedded into the shim
during installation.