Protection against vulnerabilities at boot time with Linux Secure Boot Process
Computers are vulnerable during the boot process if they are not secured. The kernel, hardware peripherals and user space processes are all initiated at boot and any vulnerability in the boot firmware can have cascading effects on the entire system.
When enabled and fully configured, UEFI secure boot helps the software running on top of UEFI resist attacks and infection from malware. UEFI secure boot detects tampering with boot loaders, key operating system files, and unauthorized option ROMs by validating their digital signatures. Detections are blocked from running before they can attack or infect the system.
UEFI secure boot works like a security gate. Code signed with valid keys (whose public key/certificates exist in the DPU) gets through the gate and executes. However, UEFI secure boot blocks at the gate and rejects a code that has a bad signature or no signature.
How it works
The boot process is authenticated by default. Authentication is based on the verification of digital signatures.
Integrity verification
The integrity of the boot firmware must be proven before trust is established in user space processes. This requires a secure mechanism to establish integrity.
Such a mechanism should be implemented into low level computer initialisation firmware like UEFI, as validating the boot process integrity at this low level assures that a device has started up in a secure state.
Standard requirements and recommendations for boot integrity measurement are following (NIST 800-155):
- Enable endpoints to measure the integrity of all executables and configuration metadata at boot time
- Securely transmit measurements of integrity
- Provide the hardware support necessary to implement credible root of trust for integrity measurements
The root of trust is the most critical element for integrity determination. It can be implemented in hardware through secure elements or Trusted Platform Module (TPM) or coded in software using cryptographic libraries (Trusted Execution Environment).
Chain of Trust
Each component in the boot sequence cryptographically validates the authenticity of the subsequent component in the boot sequence. Every component is measured before it is loaded in the runtime memory space. If an improper or unsigned component is detected, the boot process is stopped.
Digital keys
We can use either of the hardware or software root of trust for secure boot. Security admins can create and store the digital keys used to validate the boot sequence in either a secure element, a TPM device or a software TEE
Typical Boot Process
When an Ubuntu machine boots, it goes through 4 main phases.
- BIOS phase- firmware on motherboard, typically stored as a form of read only memory (ROM), contains code to initialize the hardware components of the computer and obtain the code for the bootloader.
- Bootloader phase- loads the operating system into memory along with an inital ram disk filesystem (initrd).
- Kernel phase- the kernel executes the init script inside the initrd filesystem. This loads hardware drivers and mounts the root partition.
- System startup- the operating system loads system daemons and services, sets up the network, mounts file systems, starts system logging, and performs other initialization tasks.
It is common for a 512-bit partition to be present on Linux systems called the Master Boot Record (MBR). This partition contains the bootloader (GRUB, LILO, yaboot, or others) and boot records. This is one of the places that Linux can be booted from.
Pre-bootloader (Shim)
When enabling Secure Boot, it is important to understand shim. In the context of SecureBoot, a shim is a pre-bootloader program that is designed to work with Secure Boot firmware. It allows for bootloaders and kernel modules to be loaded and executed if they are not included in the Secure Boot database. In Ubuntu, the shim loader is pre-installed and signed by the Microsoft certificate authority.
Secure Boot uses asymmetrical cryptography, meaning that a public and private key are used. The key pair can be generated by the user and the private key is used to sign all programs that are allowed to run, including the GRUB bootloader. The firmware on the BIOS or UEFI will use the public key to verify the checksums and signatures of programs before allowing them to execute.
Boot loader
UEFI Secure Boot allows users to install their own keys and sign boot loaders themselves, and in that case the boot loader can do whatever the user is comfortable with. Typically, that means that the boot loader must not execute any unsigned code in a firmware context, that is, before ExitBootServices is called just before jumping into the kernel.
Kernel Signing
Intention of secure boot is to protect against malicious use or modification of pre-boot code, before the ExitBootServices UEFI service is invoked. Currently, this call is performed by the boot loader, before the kernel is executed.
The kernel is the core code of the operating system, providing access to hardware and other services. The bootloader starts the kernel running. To keep kernels to a reasonable size and permit separate modules for separate hardware, modern kernels also use a file system which is present in memory, called an 'initrd' for 'initial ram disk'.
Both the kernel file to load and the initial ram disk are normally specified as options to the boot loader.
The kernel launches the init script inside the initrd file system, which loads hardware drivers and finds the root partition.
System startup
After the kernel is running, the remainder of the operating system is brought online.
First the root partition and filesystem is located, checked and mounted. Next the init process is started, which runs the initialization scripts. These scripts involve different /etc/rc scripts and upstart events that eventually gives you a ready-to-use computer with a login screen.
Booting components
MBR (IBM-compatible PCs)
The master boot record is the first sector on a disk and contains in general a partition table for the disk and a simple boot loader. This simple boot loader will in most cases just look for an active partition on the same disk and jump to the boot sector on that partition. The boot sector will contain the real boot loader.
GRUB Boot loader
Because the GRUB boot loader provides menus of choices and can handle many different forms of hardware, it is larger than the code which can fit in a single MBR. It has 3 stages: stage 1 in the MBR, stage 1.5 in the remainder of the first cylinder of the disk, and stage 2 within in file on the disk.
Grub will find the /boot/grub/menu.lst which configures its interactive menu. The location of the menu.lst, as well as stage1.5 and stage2 files, is hard-coded into grub when it is installed to the boot sector. Grub locates and loads the kernel and the initrd, using BIOS calls and its build-in recognition of file systems (thanks to the different available stage1.5 parts). And finally boots the kernel.
In some cases, the operating system is split over several partitions (like /usr), and these partitions are mounted by the boot scripts as soon as they can be.
Chain of Execution
- First, the BIOS has to find the boot loader and this depends on your hardware's capabilities.
- Second, the boot loader has to find the kernel and initrd. It will likely use BIOS calls, so this again depends on your BIOS.
- Finally, the kernel will boot and must, with the help of the initrd, find the root partition
root partition
The root partition with the operating system can be somewhere completely different than the kernel, for instance on another drive or on a remote computer. In some cases the kernel may not find the root partition on the disk, because the initrd is missing the modules to access the partition. If this your case, rebuild your initrd to include the missing modules (see man mkinitramfs and man update-initramfs).
References