||<>|| CVE-2019-20810 == GRUB2 UEFI Secure Boot Bypass (aka There’s a Hole in the Boot/BootHole) (CVE-2020-10713) == It was [[https://www.eclypsium.com/2020/07/29/theres-a-hole-in-the-boot/ | discovered]] that GRUB2 contained various vulnerabilities that would allow UEFI Secure Boot to be bypassed. A local attacker with administrative privileges (or with physical access to the system) could use this issue to circumvent GRUB2 module signature checking, resulting in the ability to load arbitrary GRUB2 modules that have not been signed by a trusted authority and hence bypass UEFI Secure Boot. A number of separate CVEs were allocated for these various vulnerabilities: || '''CVE''' || '''Description''' || || CVE-2020-10713 || Crafted grub.cfg file can lead to arbitrary code execution during boot process || || CVE-2020-14308 || grub_malloc does not validate allocation size allowing for arithmetic overflow and subsequent heap-based buffer overflow. || || CVE-2020-14309 || Integer overflow in grub_squash_read_symlink may lead to heap based overflow. || || CVE-2020-14310 || Integer overflow in read_section_from_string may lead to heap based overflow. || || CVE-2020-14311 || Integer overflow in grub_ext2_read_link leads to heap based buffer overflow. || || CVE-2020-15705 || Failure to validate kernel signature when booted without shim || || CVE-2020-15706 || Use-after-free in grub_script_function_create || || CVE-2020-15707 || Integer overflows in efilinux grub_cmd_initrd and grub_initrd_init leads to heap based buffer overflow || === DBX Update === Remediation of this vulnerability involves not only updated versions of grub2, but also an update to the UEFI Secure Boot DBX entries so that previously released vulnerable versions of grub2 are denied from being loaded. In the case of Ubuntu, this is achieved by adding the 2012 Canonical UEFI on-line signing key to the UEFI DBX as this was used to sign all grub2 binaries with this vulnerability. Fixed grub2 binaries are now signed by a new 2017 Canonical UEFI on-line signing key. The update for the UEFI DBX will be provided by an updated version of the `secureboot-db` package in Ubuntu at a later date, once this has undergone validation. For users wishing to apply the DBX update before this is released for Ubuntu, it can be obtained from the [[https://uefi.org/revocationlistfile | UEFI Forum Revocation List File]]. Dual-boot and multi-boot users need to take special care to update all their operating systems before installing DBX updates, whether received from Ubuntu, another operating system, or via the UEFI Forum. Updating the DBX list is similar to a BIOS update: Secure Boot is a feature of the motherboard and is shared in common among all operating systems on the computer. An update from another operating system may include DBX updates that will prevent you from booting unrelated operating systems. We expect other operating systems to release staggered updates that will provide new GRUB bootloaders before they release DBX updates. We do not know when other operating system vendors will release DBX updates. Ubuntu currently plans to release our DBX update in the near future. Please plan to boot into every operating system on your multi-boot systems and install updates as soon as your other operating system distributions publish updates for this issue. === 16.04 LTS FIPS === Currently, the versions of `grub2` / `grub2-signed` in Ubuntu 16.04 LTS do not enforce Secure Boot signature verification because the Linux kernel provided for 16.04 LTS FIPS is not signed. In conjunction with the remediation of this issue, the forthcoming re-certified FIPS kernel for Ubuntu 16.04 LTS will be signed and `grub2` / `grub2-signed` packages *will* enforce Secure Boot validation of the kernel. Until this updated kernel is available for 16.04 LTS FIPS customers, it is advised that for customers who have Secure Boot enabled with 16.04 LTS FIPS, to pin the FIPS repository on their machine to avoid `grub2` / `grub2-signed` updates as follows: {{{ $ cat < ## * YYYY MMM DD: ## * YYYY MMM DD: === References === * https://www.eclypsium.com/2020/07/29/theres-a-hole-in-the-boot/ * https://ubuntu.com/security/notices/USN-4432-1 * https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/ADV200011 * https://access.redhat.com/security/vulnerabilities/grub2bootloader === Recovery === In the unlikely case that updating `grub2`/`grub2-signed` results in boot failure, the system can be recovered by downgrading `grub2`/`grub2-signed` from a separate running Ubuntu session. In the case of a physical machine, this can be done via the bootable Ubuntu Live CD / USB installer. In the case of a machine in the cloud, a separate instance on the same cloud availability-zone is required. In both cases, the final steps are the same - mount the root volume / device from the affected system into the livecd / separate cloud instance, chroot into this and use `apt` to downgrade `grub2`/`grub2-signed`: ==== Prepare the chroot ==== Preparing the chroot will be different depending on if this is a physical install or cloud instance. ===== Physical machine ===== 1. [[ https://ubuntu.com/tutorials?topic=desktop | Create a bootable Ubuntu CD/DVD/USB image ]] and then when booting this, select ‘Try Ubuntu without installing’. You can find current installation media at http://releases.ubuntu.com/ and old installation media at http://old-releases.ubuntu.com/releases/. 2. Within the livecd environment, mount the root partition from the affected disk as well as various ephemeral file-systems, and chroot into it: {{{ $ sudo mount $ROOT_PARTITION /mnt # see with ‘gdisk -l /dev/ $ for i in /sys /proc /run /dev /dev/pts ; do sudo mount --bind "$i" "/mnt$i"; done $ sudo mv /mnt/etc/resolv.conf /mnt/etc/resolv.conf.bak # will restore later $ sudo cp -L /etc/resolv.conf /mnt/etc/ $ sudo chroot /mnt $ mount /boot/efi }}} ===== Cloud instances (e.g. AWS EC2) ===== These instructions use AWS EC2 as an example but the process is similar in other clouds where the root disk can be detached from the VM. Google Compute Environment instructions can be found at https://cloud.google.com/compute/docs/disks/detach-reattach-boot-disk. Azure requires deleting the VM to attach the root disk to a separate instance for recovery, those instructions can be found at https://docs.microsoft.com/en-us/archive/blogs/mckittrick/how-to-delete-a-vm-and-attach-the-os-disk-as-a-data-disk-to-a-recovery-vm-arm. 1. Create a second cloud instance (if one does not already exist) in the same availability zone as the affected machine 2. Determine the root EBS volume of the affected instance, stop that instance and detach the root volume, then attach it to the second cloud instance from above {{{ instance_a=i-XXXXXXXX # the affected instance instance_b=i-YYYYYYYY # the second instance root_device=$(aws ec2 describe-instances \ --instance-ids $instance_a \ --output text \ --query 'Reservations[*].Instances[*].RootDeviceName') volume=$(aws ec2 describe-instances \ --instance-ids $instance_a \ --output text \ --query 'Reservations[*].Instances[*].BlockDeviceMappings[?DeviceName==`'$root_device'`].[Ebs.VolumeId]') aws ec2 stop-instances --instance-ids $instance_a aws ec2 detach-volume --volume-id $volume --output text --query 'State' aws ec2 attach-volume --volume-id $volume --instance-id $instance_b --device /dev/sdj }}} 3. `ssh` into the second instance 4. Mount the affected volume and chroot into it {{{ $ sudo mount /dev/xvdj1 /mnt $ sudo mount /dev/xvdj15 /mnt/boot/efi $ for i in /sys /proc /run /dev /dev/pts; do sudo mount --bind "$i" "/mnt$i"; done $ sudo mv /mnt/etc/resolv.conf /mnt/etc/resolv.conf.bak # will restore later $ sudo cp -L /etc/resolv.conf /mnt/etc/ $ sudo cp /cdrom/ubuntu/pool/main/g/grub2*/*deb /mnt/tmp $ sudo chroot /mnt }}} ==== Downgrade `grub2`/`grub2-signed` to the previous version for recovery ==== The previous version of `grub2`/`grub2-signed` will be different depending on the given Ubuntu release - these are summarised in the following table for amd64 (for other architectures, navigate to them via https://launchpad.net/ubuntu/+source/grub2 and https://launchpad.net/ubuntu/+source/grub2-signed for your release): || '''Release''' || '''Previous grub2 Version''' || '''Previous grub2-signed Version''' || || 20.04 LTS || [[ https://launchpad.net/ubuntu/+source/grub2/2.04-1ubuntu26/+build/19165233/+files | grub2 2.04-1ubuntu26 ]] || [[ https://launchpad.net/ubuntu/+source/grub2-signed/1.142.1/+build/19407251/+files | grub2-signed 1.142.1 ]] || || 18.04 LTS || [[ https://launchpad.net/ubuntu/+source/grub2/2.02-2ubuntu8.15/+build/18831561/+files | grub2 2.02-2ubuntu8.15 ]] || [[ https://launchpad.net/ubuntu/+source/grub2-signed/1.93.16/+build/18831639/+files | grub2-signed 1.93.16 ]] || || 16.04 LTS || [[ https://launchpad.net/ubuntu/+source/grub2/2.02~beta2-36ubuntu3.23/+build/18024504/+files | grub2 2.02~beta2-36ubuntu3.23 ]] || [[ https://launchpad.net/ubuntu/+source/grub2-signed/1.66.23/+build/18028097/+files | grub2-signed 1.66.23 ]] || || 14.04 ESM || [[ https://launchpad.net/ubuntu/+source/grub2/2.02~beta2-9ubuntu1.17/+build/16522994/+files | grub2 2.02~beta2-9ubuntu1.17 ]] || [[ https://launchpad.net/ubuntu/+source/grub2-signed/1.34.20/+build/16548803/+files | grub2-signed 1.34.20 ]] || Once the required versions are identified from the table above, `grub2`/`grub2-signed` can be downgraded as follows from within the chroot environment. Since the previous versions are no longer available via apt, we must download the previous versions of debs and install them with dpkg. This example uses the versions for Ubuntu 18.04 LTS with typical installation packages, so these should be replaced with the appropriate versions for the given install and for packages (see '`dpkg -l | grep grub`' to see what to fetch via `wget`). Eg: {{{ # inside chroot from above (can use the links from the above table for GRUB2_LP_URL and GRUB2_SIGNED_LP_URL) GRUB2_VERSION=2.02-2ubuntu8.15 GRUB2_LP_URL=https://launchpad.net/ubuntu/+source/grub2/$GRUB2_VERSION/+build/18831561/+files GRUB2_SIGNED_VERSION=1.93.16 GRUB2_SIGNED_LP_URL=https://launchpad.net/ubuntu/+source/grub2-signed/$GRUB2_SIGNED_VERSION/+build/18831639/+files $ cd /tmp # on focal, omit grub-efi and grub-efi-amd64 $ for i in grub-common grub-efi grub-efi-amd64 grub-efi-amd64-bin grub2-common ; do wget $GRUB2_LP_URL/${i}_${GRUB2_VERSION}_amd64.deb ; done $ wget $GRUB2_SIGNED_LP_URL/grub-efi-amd64-signed_${GRUB2_SIGNED_VERSION}+${GRUB2_VERSION}_amd64.deb $ dpkg -i ./grub*.deb $ cp -df /etc/resolv.conf.bak /etc/resolv.conf }}} Then finally exit the chroot and unmount the root device / volume (and detach + re-attach it to the original instance for a cloud instance). ## ## ==== Public Cloud Image updates ==== ## * Amazon AWS: ## * Windows Azure: ## * Google Compute Engine: ## * Ubuntu Core Images: ## Cloud Images dailies will start appearing within 4 hours of the USN announcement. ## At the direction of the security team, the Cloud Image Team will start manually ## releasing new images to the public cloud. === Known issues === ==== Existing Cloud / MAAS instances may fail reboot ==== For Cloud and MAAS images there was a cloud-init issue, [[ https://bugs.launchpad.net/cloud-init/+bug/1877491 | bug #1877491 ]], where the grub install devices were not correctly set at first boot. Existing instances that received the fix for that bug did not have the configuration fixed. There is an underlying grub issue, [[ https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889556 | bug #1889556]], where an incorrect install device causes grub-install to fail during package upgrade but the installation still proceeds, whereas it should fail the grub install. This leaves the system with grub modules on the filesystem that are newer than grub core on the boot device which causes the instance to fail to reboot, [[https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889509 | bug #1889509]], from the mismatch. ===== Workaround ===== Before rebooting run `sudo dpkg-reconfigure grub-pc`. A wizard will walk you through the grub configuration options. You can select the default options until you get a list of install devices. If your instance is affected by this issue you will first see a message that the install device is no longer present: {{attachment:dpkg-reconfig_grub-pc_no-longer-present.png|The GRUB boot loader was previously installed to a disk that is no longer present, or whose unique identifier has changed for some reason.}} Proceed to the next screen and select all devices when prompted for a grub installation device. {{attachment:dpkg-reconfig_grub-pc_install-devices.png|GRUB install devices:}} At the end of the reconfiguration grub-install will update the bootloader. {{{ Installing for i386-pc platform. Installation finished. No error reported. Generating grub configuration file ... Found linux image: /boot/vmlinuz-4.4.0-1109-aws Found initrd image: /boot/initrd.img-4.4.0-1109-aws done }}}