SSD Advisory – GNU GRUB Command Injection

TL;DR

Find out how a vulnerability in GNU GRUB allows users on a Linux system to inject commands into the process of grub-mkconfig which allows them to execute arbitrary commands with elevated privileges.

Vulnerability Summary

GRUB ships with a script that allows generating /boot/grub/grub.cfg based on the operating systems installed on all the devices attached to the current system. The script is called grub-mkconfig. On Debian and systems based on Debian grub-mkconfig is run every time a kernel or driver is installed, upgraded or removed.

When grub-mkconfig detects a GNU/Linux system installed on a different media device, it examines that system’s /boot/grub/grub.cfg, looks at menuentrys inside and generates new menuentrys for the current system’s grub.cfg based on that info. When a new menuentry is being generated, certain GRUB commands (like linux and initrd) get copied from the “old” one.

grub-mkconfig doesn’t implement proper parsing of GRUB commands. When grub-mkconfig copies GRUB commands, it copies the whole lines that start with those commands. Inserting a semicolon after certain GRUB commands allows injecting GRUB commands that grub-mkconfig would not have copied otherwise.

CVE

CVE-PENDING

Credit

An independent security researchers, NyankoSec, has reported this vulnerability to the SSD Secure Disclosure program.

Vendor Response

The vendor has been informed and has released patches that were distributed across all affected distributions of Linux and other potentially affected OSes – more details are available here: https://lists.gnu.org/archive/html/grub-devel/2020-07/msg00034.html

Vulnerability Analysis

Basic details

grub-mkconfig detects GNU/Linux systems based on the presence of the following files:

  • ld.so. It can be placed at several different locations and can have various suffixes like ld-linux.so.2, creating an empty /lib/ld.so is enough.
  • /boot/grub/grub.cfg
  • A file named after a kernel mentioned in /boot/grub/grub.cfg. For example: /vmlinuz. This file can be empty.

grub-mkconfig detects operating systems on every partition, regardless of whether that partition is mounted or not.

grub-mkconfig detects operating systems on any kind of media: hard disks, SSDs, USD drives, SD cards, etc.

Potential exploitation methods

Being able to inject arbitrary GRUB commands is nice, but we can’t know beforehand what kernel and initrd our target is using.

We might assume that /vmlinuz and /initrd.img are available, generate a menuentry based on that and force its execution with settimeout=0 and set default=$our_menuentry, but this approach is not robust.

The target system may have no /vmlinuz or /initrd.img, maybe using a non-standard init, etc.

AFAICT, it may also make circumventing full-disk encryption impossible in some cases. In general,this approach may break out target’s system, which is not something that we want.

It would be nice to be able to examine various menuentrys at runtime and hijack their linux commands. Unfortunately, GRUB script is not expressive enough to allow us to do that. To achieve that, we need a GRUB module.

Hijacking GRUB via module

To exploit the vulnerability in GRUB we will create a GRUB module called ggh.mod.

When ggh.mod is loaded, it registers a hook that fires up after GRUB has finished processing the entire grub.cfg file.

That hook goes through each menuentry loaded by GRUB from the grub.cfg file and replaces any linux or linux16 command with a hijacked version.

The hook also deletes any menuentry that contains a certain magics tring (“ggh_442ecb7e12dc4b8e”). Our exploit generates two dummy entries with that kind of name.

The only drawback of this approach is that the target must keep the infected device attached to the system until it reboots.

Flow of Attack

A user having control over a device that is one of the above can place the files that will be processed by GRUB such that when the kernel (for example) is upgraded and grub is subsequently called to install itself – this GRUB module we created will get called and modify the grub.cfg file with our controlled content.

Due to the complexity of the Exploit we will not be including it in this advisory, we are willing to share the Exploit with people that contact us via email.

Exploit Compiling

These instructions have been tested on Debian 9 and 10. The same instructions should work on any new version of Ubuntu as well.

A GRUB module compiled on one distro will work with any other reasonably new distro or GRUB version.

sudo apt build-dep grub2

Edit src/ggh_shellcode.1 to your liking or keep the default payload. Do not touch src/ggh_shellcode.2 unless you know what you are doing. Also, make sure that src/ggh_shellcode.1 is not too large: it gets base64-encoded and is passed as an argument to the Linux kernel, and Linux is not very happy about arguments over a certain size.

Run make. It will download the source code for GRUB (apt source grub2), compile ggh.mod and create build/rootfs.

Find out the UUID of the device you want to infect. Try findmnt -o TARGET,UUID or blkid.

Replace the dummy UUID (00000000-0000-0000-0000-000000000000) in build/rootfs/boot/grub/grub.cfg with the one you have just discovered.

Mount the device you want to infect and copy all the files in build/rootfs to it:

cp -RT build/rootfs /path/to/your/device

Now you just need to wait for someone to install something that requires upgrade-grub / grub-mkconfig to occur.

Comments
Comments are closed.

Interested in Remote Code Execution? You may be interested in these:

Looking to submit a Remote Code Execution vulnerability?

Talk to us!