Full Report
Full disk encryption for an unintended computer is a surprising difficult problem to solve. A classic way of doing this is using a TPM to store an encryption key but only having the encryption key accessible if the computer is in the right state via policy sessions. Because of the policy, it's not possible to modify the running code. Because of the FDE, it's not possible to modify the file system, making for a secure system. The above approach has a problem with bus sniffing to get the key but working very well otherwise. An unattended disk encryption setup still allows a user to view the output of the boot process or manually enter the key if something goes wrong. Usually, a screen is presented for interacting with this functionality but quickly goes into the boot process if the TPM is active and working. In the automatic flow, there is room for logic bugs. If an attacker can interact with the system after decryption but before the full load of the OS, then they could cause havoc. In 2016, Debian's cryptsetup startup script allowed for holding the ENTER key to gain root access to an early boot environment. Since this was post decryption, an attacker with a root shell could modify the file system or do whatever they want to compromise the system. The author decided to perform fuzzing to see what would happen. This was using an Atmel Microcontroller to enter key presses very fast, in a similar way to a rubber ducky. The program pressed the ENTER key every 10 milliseconds, which is much faster than just holding down the key on a keyboard. By doing this, the key presses restrict the auto decryption and autoboot from happening. Because of all the failures, it goes into a recovery mode with a root shell in an early boot env. Once there, we can call basic TPM commands to decrypt the drive, bypassing the FDE. Why does this occur? It's super complicated. An agent plugin is used for systemd with a pool of different responders from these plugins. When using both dracut and clevis at the same time, Clevis implements a systemd password agent for unlocking, but the user may also enter a password using the normal interactive agent. For whatever reason (which I don't fully get), this puts it into a very weird state that drops us into an emergency shell at the end. A super interesting flaw in the low level process. It's fascinating that simply pressing enter can bypass the boot process. This architecture seems to be at fault; I'd wonder if similar types of bugs exist in this system from this design.
Analysis Summary
# Vulnerability: Mashing Enter to Bypass Full Disk Encryption (TPM/Clevis/Dracut)
## CVE Details
- **CVE ID**: Not explicitly assigned in the article (Note: This is a design/logic flaw involving the interaction of multiple components: Clevis, dracut, and systemd. It shares characteristics with historical vulnerability **CVE-2016-4484**).
- **CVSS Score**: Estimated 6.8 (Medium/High - Physical Access required)
- **CWE**: CWE-287 (Improper Authentication), CWE-693 (Protection Mechanism Failure)
## Affected Systems
- **Products**: Linux distributions using TPM-based unattended unlocking.
- **Versions**: Specifically verified on Ubuntu 20.04.
- **Configurations**: Systems using a combination of **RedHat’s Clevis**, **dracut** (initramfs framework), and **systemd** to implement unattended LUKS (Linux Unified Key Setup) decryption via a Trusted Platform Module (TPM).
## Vulnerability Description
The vulnerability is a logic bug in the early boot (initramfs) sequence. When a system is configured for unattended TPM unlocking, it employs a systemd password agent (via Clevis) to automatically provide the decryption key. However, the system remains "interactive" to allow for manual password entry if the TPM fails.
By "mashing" the ENTER key at a very high frequency (e.g., every 10ms using a microcontroller like an Atmel or a Rubber Ducky), an attacker interferes with the systemd password agent's polling/response cycle. This creates a race condition or state conflict between the Clevis "auto-responder" and the "manual" input prompt. This conflict causes the boot process to fail and drop the user into an **emergency shell** (initramfs root shell). Because the disk decryption key is still accessible via the TPM context or remains in a state where it can be queried by the shell, the attacker can then manually trigger the TPM unlock and gain full access to the encrypted filesystem.
## Exploitation
- **Status**: PoC available (tested with Atmel Microcontroller/USB HID injector).
- **Complexity**: Low (requires only a high-frequency keyboard input device).
- **Attack Vector**: Physical (requires access to the USB port/keyboard).
## Impact
- **Confidentiality**: High (Full access to encrypted disk contents).
- **Integrity**: High (Ability to modify the OS, plant backdoors, or alter system files).
- **Availability**: High (Ability to wipe the disk or corrupt the boot process).
## Remediation
### Patches
- There is no single "patch" as the issue stems from the architectural interaction of `systemd`, `dracut`, and `clevis`. Users should ensure all these packages are updated to the latest versions provided by their distribution (e.g., Ubuntu, RHEL).
### Workarounds
Modify the **kernel command line** parameters to prevent the system from dropping into an interactive shell upon failure:
1. Add `rd.shell=0` to disable the emergency shell.
2. Add `rd.emergency=reboot` to force the system to reboot immediately if the boot process fails, preventing shell access.
## Detection
- **Indicators of Compromise**: Physical evidence of unauthorized USB devices. Logs showing multiple failed boot attempts or unexpected entries into emergency mode.
- **Detection Methods**: Monitor changes to the kernel command line parameters or the initramfs image.
## References
- hxxps[://]pulsesecurity[.]co[.]nz/articles/tpm-luks-bypass
- hxxps[://]github[.]com/latchset/clevis
- hxxps[://]hmarco[.]org/bugs/CVE-2016-4484/CVE-2016-4484_cryptsetup_initrd_shell[.]html