KeyHijack: The Design Flaw in coreboot’s UEFI Secure Boot Support
Acronym | Description | |
---|---|---|
CA | Certificate Authority | Root-of-Trust that verifies an entity's identity |
EDK2 | EFI Development Kit II | UEFI reference code |
SMM | System Management Mode | A highly privileged mode of execution on the x86 architecture, sometimes mistakenly/trivially called "ring -2" |
SPI | Serial Programmable Interface | A hardware interface commonly used to connect flash storage chips that store firmware |
TPM | Trusted Platform Module | |
TPM PCR | TPM Platform Configuration Register | TPM registers that store the current 'state' of measured firmware/OS code and data |
UEFI | Unified Extensible Firmware Interface | A prolific firmware industry standard |
What is UEFI Secure Boot?
Secure Boot is a core feature of UEFI that protects the chain-of-trust. With proper implementation and configuration, it ensures that the user's bootloader and operating system start as desired, without malicious modification.
For a UEFI driver, option ROM, application or bootloader to be allowed to boot, it must be signed by a trusted key, with the corresponding certificate present in the firmware. The infrastructure is designed similarly to what’s used on the web, enabling both extensibility and the ability to exchange a CA when needed: a root CA signs several intermediate CAs, which will sign many server certificates. As there is only one platform manufacturer, there is one more layer of indirection:
- PK: The platform key. There can only be one, and it’s typically held by the manufacturer of the hardware/the builder of the firmware, although it is replaceable by a physically present user. This is similar to a root CA.
- DB: The database (or list) of approved certificates, similar to a set of intermediate CAs. Any of these can sign an application to authorise it to boot. Common examples of certificates found in the DB are Microsoft’s first-party CA, which signs their own bootloaders, and their third-party CA, which signs applications like shim. It can also be a list of approved file hashes, but this is uncommon.
- DBX: A database of denied file hashes/certificates. DBX has priority over DB: If an application is found on this list, regardless of whether an entry in DB authorises it, it may not execute.
- KEK: The key-exchange key. As it can be difficult to coordinate updates with the owner of the PKs, the PK actually signs KEKs corresponding to the DBs that will be included in the firmware, and these are responsible for signing the DB and DBX.
All of the above are stored as UEFI variables. As the integrity of these variables is critical to secure boot's operation, the UEFI variable services offer these guarantees by validating their signatures when an attempt is made to write to them. Other variables, such as those defining the chipset configuration (including security and lockdown), are often write-protected or made invisible at runtime. For security purposes, the variable services are typically located inside SMM, where they are secured against patching and other attacks (and where they are capable of unlocking the SPI controller and writing to the SPI flash).
How coreboot Supports UEFI Secure Boot
coreboot supports variables through the SMMSTORE feature, which allows a payload to write data to the SPI flash by ‘calling into SMM’ (triggering an SMI, or SMM interrupt) with the data it wants to write. In this way, there is minimal coupling between coreboot and the payload: coreboot provides the interface to read/write, and the payload defines the structure.
EDK2’s variable services are even modular: the variable driver is layered on top of the driver that makes the writes fault-tolerant, which is layered upon an implementation of a driver that issues relevant commands to the hardware. Implementing secure boot on top of this is then straightforward: we simply substitute the driver that would issue commands to the SPI controller with our own, which will trigger the SMMSTORE SMI handler to perform a read or write.
The Fundamental Flaw
The attentive reader may realise that if arbitrary write/erase is allowed, nothing stops another piece of code from using SMMSTORE to overwrite parts of UefiPayload’s variable store, bypassing verification and compromising the contents. Such changes would be undetectable, because the PK is self-signed: at runtime, the UEFI variable services should check that a new PK is signed by the old PK, but this attack allows replacing the PK while ignoring this check. Therefore, we haven't been able to call the SMMSTORE-based implementation of secure boot, "secure" to our customers. In short, while it was innovative in its time, SMMSTORE was not designed to support authenticated variables.
We briefly considered enhancing the SMMSTORE driver in coreboot to perform the necessary verification, perhaps as a new v3, but rejected it: the amount of code that we would have to port from EDK2 would be much too great, would be difficult to maintain by non-UEFI developers, and would compromise the objective we mentioned earlier, of keeping coreboot and the payload decoupled from each other.
While it would be possible to enhance SMMSTORE with A/B regions and a new LOCK command to protect one of these once firmware is ready to boot, as discussed in https://review.coreboot.org/c/coreboot/+/79095, this is insufficient: overwriting the PK, even after handing off to the operating system, is supposed to be permitted. The only condition is that the update passes verification.
Attack
As far as we know, nobody ever even wrote a proof-of-concept exploit for using SMMSTORE to attack UEFI secure boot, so we're not certain how likely it is an attacker would try. Practically, they may face mitigations that need to be bypassed.
Assuming root privileges, this is the attack model (although the kernel’s lockdown feature may complicate it):
Read the coreboot table data structure that describes the SMMSTORE feature to find its SMI number, the address of the buffer for communicating data to the SMI handler, etc
Locate critical UEFI secure boot variables by reading directly from the store
Use the raw write command to clear or overwrite these variables
(Secure boot has now been disabled/bypassed, after the boot-up completed (as in, not by the user in the setup menu) and authentication was skipped. The attacker can do malicious things here, like patching shim or the Windows boot manager)
Such an attack would be caught by a TPM though, and is an excellent argument for why secure and measured boot technologies should be used together, and why system administrators should configure the operating system to verify those measurements. For example, the TPM register 7 describing the platform configuration (PCR) contains the measured secure boot configuration, which is a good, minimum set of TPM PCRs to check.
Ultimately: It's an elevation of privilege vulnerability, and it's been famously difficult to protect kernels against root/SYSTEM. I believe Microsoft has a habit of fixing such bugs, but not considering them security issues, because admin accounts are trusted. Since the whole thing is about root circumventing the kernel, but the attack requires ring-0 help from the kernel for IO access, perhaps kernel lockdown mitigates it, but it is bad practice to rely on a successor in the boot chain for our own security.
Conclusion
We have outlined an attack against UefiPayload’s Secure Boot, when it is backed by coreboot’s SMMSTORE driver. A future article will outline how we tried to follow an alternative design of SMM ownership used elsewhere in the industry, the bugs we found there, and how that led to a fundamental reinvention of the SMM ownership model that implements both new ideas as well as the latest in the industry.