Startup attack analysis for Linux system full encryption

Source: Internet
Author: User

Startup attack analysis for Linux system full encryption

Recently, our tan digital technology (GDS) researchers have discussed the cold start attack on Linux system full encryption. Everyone thinks this attack is feasible, but how hard is it to execute such an attack? What is the feasibility of an attack?

Attack

Since there are no ready-made tools on the market that can perform such attacks, we have made our own tools and named them EvilAbigail. Edevil maid attacks can be targeted at any operating system. This study is intended for Linux systems that use LUKS full-disk encryption.

Generally, when the Linux system uses full encryption, a small partition is still not encrypted. This region is used to decrypt and guide encrypted disks. This partition is mounted to/boot and contains the kernel and the initial RAM disk (initrd ). Although it is also feasible to attack the kernel or bootloader, we still attacked initrd.

Initrd is a temporary file system that is called by the Linux kernel during startup. Initrd is used to prepare a root file system before it is mounted. Initrd contains the minimum set of directories and executable programs required to decrypt and mount the root file system. Once the initrd task is completed, it executes the initt_root command to unmount the initrd root file system and mount the real root file system.

In general, initrd is a cpio image compressed by gzip. The Debian-based operating system we tested is like this, but the RedHat-based operating system (Fedora, RHEL, CentOS) currently uses dracut, which contains an uncompressed cpio image. Debian-based initrds will be started using the ash shell script, while dracut will use systemd and the associated configuration method.

To execute our attacks, we chose to use a LD_PRELOAD-based bootkit, but it can also be injected into malicious kernels or executable files. The main purpose of using LD_PRELOAD is to inject a shared object to the first executable file in the decrypted root file system. The first executable file is usually/sbin/init, And the PID is usually 1. The easiest way to perform an attack is to modify the init script and export the environment variable. In this way, the environment variable is set when the cmdt_root command is executed. Because when the file system is changed, the shared object must be copied to the new system at an appropriate time (after decryption. Put the following two lines in the initrd init script and insert them before switching the file system:

cp /hack.so /${rootmnt}/hack.soexport LD_PRELOAD=/hack.so

This is feasible because the real root file system is decrypted and mounted under the temporary root file system, which is prior to the portable, and the rootmnt variable is filled with the mount point position. However, you need to re-mount the target file system to read/write, because it is read-only by default. In our example, we modified the init script and modified the script to analyze the kernel command line. Therefore, no matter what parameters are provided, the root file system is mounted in read/write mode. Another method is to add mount-o remount, rw/$ {rootmnt} to the injection command }.

However, dracut-based initrds does not contain injection points because the init executable file is a binary file rather than a shell script. This brings us three problems. Only by overcoming these three problems can we inject them into the pid 1 process.

Three questions

The first problem is to copy our binary file to the decrypted root file system. This problem is the best solution among the three problems. We can add two ExecPre commands to the systemd service file in charge of the replicte file system. This is basically equivalent to the insert script method mentioned above. The first command remounts the root file system in read/write mode, and the second Command performs the copy operation.

The second question is about LD_PRELOAD. Because we are not modifying shell scripts, we cannot pass environment variables to this process (because it is called by the kernel), so loading our shared objects is a bit tricky. The simplest way is to first move the init binary file to another location, insert our own shell script in its original location, and then execute the original binary file. We only need two lines of code. The first line exports LD_PRELOAD, and the second line executes the original systemd binary file. Note that the pid 1 process in initrd is injected, rather than the pid 1 of the final root file system.

The third problem is that before the switch-root command is called, systemd uses the clearenv () function to clear all environment variables. Because this function is part of the standard library, we can rewrite this function so that the injected process will call our function instead of the original function. We don't really care about clearing environment variables. The clearenv () function we write clears all environment variables and injects our LD_PRELOAD variables into the environment. Because clearenv () is called only once, our modifications will not cause any side effects.

After these three problems are solved, the new shared objects will be copied to the encrypted root file system, our LD_PRELOAD will be injected into the pid 1 Process of the target file system. Next, we can obtain the user password used for decryption.

For Debian initrds, the executable file requires the user to enter the password, and then decrypt and mount the root file system. We can inject our script into the pipeline process to obtain the password.

As for systemd, it uses Unix domain sockets for a more complex inter-process communication. We chose to attach the file system instead of this process. This is also a library function. It is dynamically loaded from the library and called from systemd, so we can hook this function. The hard disk decryption function is called crypt_activate_by_passphrase. This function uses the password as the char array. By using the hook function, we can get the password. We want to wrap this original function, so we use dlsym to open the real function and call it. However, we will save the password for future retrieval.

To "save" the password, we simply add it to the shared object of the root file system. We chose this method because we already know that this file exists and will be copied. Using this method will also reduce the number of disk files we are exposed. To get the PASSWORD, we will read the end of our own file (located using the LD_PRELOAD variable) and set it to the value of the PASSWORD environment variable in our bounce shell, therefore, you can use the 'getenv password' command to obtain the PASSWORD used to decrypt the disk. Since python is installed on all our target hosts by default, we use the python meterpreter bounce shell.

Solution

There are many ways to solve this problem. However, even with these solutions, if attackers can physically access computers and have enough time to refresh BIOS/UEFI, they will not be able to prevent them.

The first method is to place bootloader, kernel, and initrd on an external USB flash disk, and then start from the USB disk to replace the/boot partition. But this method is very bad for users, because they should remember to unplug the USB flash disk when they leave the notebook, and unmount the/boot partition safely if they do not unmount it. It is also difficult to update. You need to plug in a USB flash drive to update the initrd/kernel.

Another solution is to completely disable the startup system from external media. In this way, there is no possibility of automatic attacks, but in some cases, for Debian initrds that contains shell, you can manually mount and modify initrd from initrd. This can be done through an automatic keyboard device, bypassing the restriction that the system cannot be started through external media.

In addition, you can enable the BIOS boot password so that no one can start the computer.

However, If attackers have enough time to remove the hard disk and start the hard disk in their own notebook, the last two solutions will not work.

Finally, the safest solution is to extend SecureBoot to initrd. SecureBoot can verify the bootloader and kernel. If it can verify the signed initrd, it will be difficult to modify anything in the/boot partition without trace. However, If attackers can disable secureboot by flushing the BIOS/UEFI, this solution is useless.

The best way to prevent such attacks is not to let your devices fall into the hands of attackers. Our PoC attacks can attack all target hosts within 2 minutes, but in the real world, attackers can also make payload attacks against specific targets, so that the payload can attack devices in just a few seconds.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.