██████╗  ██████╗ ██╗  ██╗ █████╗ 
╚════██╗██╔═══██╗██║  ██║██╔══██╗
 █████╔╝██║   ██║███████║███████║
 ╚═══██╗██║   ██║██╔══██║██╔══██║
██████╔╝╚██████╔╝██║  ██║██║  ██║
╚═════╝  ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝

Welcome to 3OHA, a place for random notes, thoughts, and factoids that I want to share or remember.



18 December 2022

Bash malware (I): The AWFULSHRED wiper

The AWFULSHRED wiper for Linux (hash bcdf0bd8142a4828c61e775686c9892d89893ed0f5093bdc70bde3e48d04ab99) is implemented in 422 lines of a Bash script. It is attributed to the Sandworm group and was used against an Ukrainian energy provider in April 2022. The ESET's Industroyer2 report provides more context about this operation.

The original sample is mildly obfuscated by replacing some literals, variables and function names by short random strings. I prepared a beautified version by renaming variables and functions names with more meaningful choices to improve code readability. I also added some comments scattered throughout the code for those not familiar with Bash scripting or the core commands used by the sample.

Both the original and the beautified version are availabe in this GitHub repository.

Operation

AWFULSHRED works as follows:

  1. It destroys its program file by first shredding it and then removing the file.
  2. It clears and disables the bash history and removes the ~/.bash_history file.
  3. It frees the page cache, disables swapping on all known swap devices (swapoff -a) and synchronizes data on disk with memory.
  4. The core wiping process is launched if all the following 4 conditions are met (checked in this order):
    1. The script is running with root privileges.
    2. Bash version is higher than 3.
    3. The machine is running a Linux kernel 2.6.27 or higher.
    4. The commands dd, uname and sed are available.
  5. If available, shred is selected as preferred wiping command with just 1 pass instead of the default 3. If shred is not installed in the system, it uses dd (sourcing from /dev/urandom).
  6. The script then runs the core destructive steps:
    1. It checks (using systemctl is-active) if the following services are running: apache, http and ssh. Each running service in that list is stopped, disabled, and their systemd files are removed. The systemd daemon is then relaunched.
    2. It deletes (using rm -rf) the /boot, /home and /var/log directories.
    3. It finds disks attached to the system using two methods: (i) processing the output of lsblk (system block devices), considering only those of type disk; and (ii) enumerating the set {hda, hdb, ..., hdz, sda, sdb, ..., sdz} and checking if the associated /dev/$name exists.
    4. If the previous step returns at least one disk, it wipes them in parallel using the method selected above (shred or dd).
  7. It deletes the root directory recursively (rm -rf / --no-preserve-root).
  8. It attempts to remove the wiper again (same as step 1).
  9. It forces an immediate system reboot using the magic SysRq key trick.

Analysis

These are some notes on its design:

  1. The very first step taken by AWFULSHRED is to self-destruct by shredding its own file. This is a sensible decision in order to remove potential evidence in case the process fails prematurely. The odd part about it is that this process uses shred without checking if the command is available on the system—which probably is, since it is common in most distributions. But if this is the case, it doesn't make much sense to later check if shred is unavailable to use dd instead. This has not been thought through properly.
  2. Same as above, in step 4.c it retrieves the kernel name and version using uname. Step 4.d does not make much sense then, except perhaps for sed.
  3. Checking if it's running with root privileges happens too late in the code. By the time this is tested, the script has already attempted to run swapoff -a, which requires root privileges. Further, if it doesn't have root privileges, it still tries to rm -rf / --no-preserve-root >/dev/null 2>&1 and to reboot the system, none of which will obviously run.
  4. The first method used to identify disks relies on the output of lsblk. It then uses sed to remove extra spaces. However, the reading loop uses the original lsblk output instead of the cleansed one. This is most likely a bug.
  5. AWFULSHRED uses just 1 writing pass for the shred command instead of the default number of 3 passes. This decision could be motivated by performance reasons. The process is done in parallel for each disk attached to the system. This is also a sensible choice since the shredding might take hours for disks of considerable size.
  6. shred relies on the assumption that the file system overwrites data in place. This is not the case on some modern file systems such as journaled or log-structured designs (e.g., ext3 and some provided by AIX and Solaris), RAID-based file systems, or NFS v3 which caches in temporary locations. For these cases, shred is not guaranteed to be effective. As a side note, traditional secure deletion processes based on overwriting are not effective against Solid State Drives (SSDs), which are known to be hard to wipe.

Overall, AWFULSHRED is incredibly simple, and possibly effective. There are some oddities in the code that point at a rushed design that has not been tested thoroughly. This isn't news. The economics of malware development are relatively well understood, and developers typically follow the path of least resistance. I was expecting this particular sample to be one notch over the average, but it's not the case. It probably doesn't need to.



© 2022 Juan Tapiador