A personal honeypot of mine picked up on a particularly nasty attack today, in which both a cryptomining binary and TWO remote access tools were dropped and executed. Lets take a trip and explore this Miner/Backdoor hybrid attack, one that is likely perpetrated every second across the internet.
The Dota Campaign (name drawn from a file name we’ll see later) obtains its initial access via weak SSH credentials. In my case, my SSH honeypot consists of a user named salvatore with a password of salvatore. We can see in my SSH log the initial login here:
Immediately upon authenticating, the attacker then executes system commands over SSH. The attacker avoids logging in interactively, however, so all the commands are passed within the actual SSH command. Because my system is a honeypot with a custom OpenSSH version, we can see the commands the attacker executed:
First, the attacker grabs a file named .x15cache via HTTP from the 54.37.70[.]249 host. Following that, the attacker then waits 10 seconds and executes this file. The attacker also goes about changing the password of the user to a random string.
Let’s take a look and see what the .x15cache file is:
So, it looks like .x15cache is just a dropper that sets up the environment, then grabs another file, hosted at the same 54.37.70[.]249 address. This second file, named dota2.tar.gz (hence the Dota name), is a tar file that likely contains the bulk of the malicious code, which is seemingly contained in a directory named .rsync. We can actually see the process of all this content being extracted from my file detection script:
Back to the .x15cache script, it then navigates into this .rsync directory, then tries to execute two files, ./cron and ./anacron. The attacker uses an || (or) statement so that ./cron is executed first, and ./anacron is executed only if ./cron fails. One of the other scripts that are within the .rsync directory (which oddly enough is never ran), gives us a good hint as to why the code is designed this way:
An i686 architecture corresponds to a 32-bit environment, while an x86_64 architecture refers to a 64-bit environment. So, it looks as if cron is a 64-bit binary, while anacron is a 32-bit binary. Running the file command on both binaries confirms this hypothesis:
Knowing this, we really only have to analyze one of the two binaries, because each is doing the same general thing, with their architecture being the only disparity.
Analyzing the cron Binary
Before jumping into any kind of deep reverse engineering, let’s see if we can get some basic information via the strings command. Immediately, I start to notice some references to “cryptonight”:
Per the wiki here, CryptoNight “is a proof-of-work algorithm. It is designed to be suitable for ordinary PC CPUs, but currently no special purpose devices for mining are available. Therefore, CryptoNight can only be CPU-mined for the time being.”
So, we know this binary has something to do with cryptomining. Let’s see what else strings can get us:
This guy right here stood out like a sore thumb. This is the help page for the xmrig command, which is a Monero CPU Miner. Also, notice that we can catch the compile time of this binary as well, May 3, 2019, which is less than a month ago.
So, it looks like we’re just dealing with cryptominer. Let’s run the binary and see if we see any network traffic, which should be an inevitability.
Upon running the binary, we see a connection established to a new host, 5.255.86[.]129 on port 80:
Now lets run tcpdump to catch all the network traffic of this connection, and analyze it in Wireshark to get a nice look into whats going on:
So, the client (us) is sending some json data to the server. Notice there is another reference to XMrig in the agent parameter, as well as cn (short for CryptoNight) in the algo (short for algorithm) parameter. This pretty much seals the deal that we’re dealing with a run-of-the-mill cryptominer.
The Second Attack Phase
The attacker certainly doesn’t stop here, however. After running the commands we saw earlier, as well as some various information gathering commands, the attacker hits us with another wave of commands a few seconds later:
This time, the attacker works in the /dev/shm directory, as opposed to /tmp. After moving to /dev/shm, the attacker grabs a file named rp and a file named .satan, from the same 54.37.70[.]249 host as before. The attacker then tries to run sudo in order to get root permissions, and run the dropped .satan script with said permissions. So, lets take a peek at this .satan file:
As you can see, this satan script digs a lot deeper than the .x15cache dropper we saw earlier. First, it creates a new systemd service file called srsync, and enables it to run automatically. The srsync service calls a script called /usr/local/bin/srsync.sh, which is dynamically built in the script as well. The srsync.sh script runs rsync.pl, a perl script, and ps.bin, presumably a binary. The rsync.pl script originates from /dev/shm/rp, which is grabbed when the .satan script itself is grabbed (check out the last screenshot). The ps.bin binary is retrieved via wget in this script, and is hosted again at the 54.37.70[.]249 host. Notice that, in the cryptomining malware, the attacker had curl as a secondary command to grab files if wget fails; that’s not the case here. This is a hint that maybe these two pieces of malware were written by different parties. Anyways, Lets take a look at both the ps.bin file and rsync.pl file.
Running a quick file command, I can confirm that ps.bin is in fact a binary, a 32-bit one to be exact:
Like we did with the cron binary, let’s run strings and see what we can find.
After taking a long look at the strings output, I start to notice some mentions of ssh. Because of this, I decide to grep for “ssh,” and the results were very telling:
The very first reference I see is a system command that’s adding an RSA public key to the ~/authorized_keys file (the command is cut off for readability purposes). This is, in effect, creating an SSH backdoor, since the attacker can always use the associated RSA private key to authenticate to the account. However, I also see many more references to ssh, which appear to be function names. Further exploring reveals more hints:
Firstly, notice the reference to a file named /root/libs/libssh-0.8.2/src/misc.c, like residual from compile time; the directory name, libssh-0.8.2, is a bit interesting. Also, notice the reference to various file names used by, for example, OpenSSH. So, the ps.bin file appears to be some sort of portable SSH binary, that also injects a key into the current user’s authorized_key file; obviously, we’re dealing with a pure SSH-based backdoor.
For some reason though, running this binary does actually work. I get no error messages, but it doesn’t spawn a process, open a socket, or anything. I tried on both a 64-bit box and a 32-bit box, both to no avail. I’ll have to look more into this binary to see whats going on, but, judging it in it’s assumed working form, we are definitely dealing with an SSH backdoor.
Let’s take a look the second file associated with the srsync service. Upon opening it in vim, we’re presented with some very unfriendly text:
This, however, is pretty easy to work around. The eval command is just going to run the outputted contents of the unpacked binary data, which at the end of the day is just going to be a perl script. So, all we really have to do is change that eval to print, and we can take a look at what this code is actually doing:
Perfect, we’re now able to see the actual Perl code. The script is actually VERY large, so I’m only going to point out the most notable portions. If you’d like to check out the entire thing, you can find it on the github page I mentioned at the beginning.
Checking out the Code
Firstly, right away I see reference to an IP address, one we haven’t seen before:
Also, it’s interesting to note that the variable names appear to be Spanish, meaning the origin of this malware is like from a Spanish-speaking actor.
Next, I locate the main loop of the program:
To summarize, this is essentially continuously listening for commands from an IRC server (the IP we saw earlier). It looks like the parse function is called to actually figure out what the command is. Let’s take a look at that function:
Right away, I notice a call to a shell function when a specific command is sent to the infected host. I can take a good guess as to what this function does, but lets take a look:
Indeed, we see that there is a system command being ran (denoted by the back-ticks) based on the $comando variable (Spanish for command). So, it looks like we’re dealing with a SECOND backdoor to the system, this time over an IRC channel. We can see via the netstat command this channel’s connection being established:
Lets actually see if we can catch some of this IRC traffic. I set up tcpdump, ran the perl script, then did some analysis via Wireshark. Here’s the full TCP stream:
Indeed we see standard IRC traffic; the client continuously attempts to obtain a nickname, and once successfully getting one, joins a channel called #root. It’s also worth mentioning that, from the server banner, we can see that the server was created May 7, 2019, less than a month ago and right around the same time as when the coin miner binary was compiled.
Back to the Perl code, there also appears to be some “special” functions available, such as a download functionality and a port-scan functionality:
Finally, there also appears to be some sort of DoS code as well:
Again, there’s a lot more involved with this script, but you’ll have to check it out yourself; I wont be diving into every individual function.
While this sort of thing certainly isn’t anything new, this particular Dota campaign is particularly interesting in that it has TWO forms of persistence, and drops a particularly large amount of files. It definitely appears as if the cryptomining aspect of the attack and the backdoor/persistence aspect of the attack were built by two different parties, but ultimately it is one actor utilizing both simultaneously. I hope this was an enjoyable read, and feel free to contact me on Twitter @kindredsec for any questions!
.satan : 36e692c1e58b53f54ae4966d15fdfa84
rsync.pl : 52a422722c479d8c5483d2db9267e4cd
ps.bin : 04d0658afae3ea7b0fdaf6a519f2e28c
dota2.tar.gz : 2cfb1ad304940ae7e3af954d5c1d1363
.x15cache : 6d6fb279bb78b25413a441e4bfd3ded9
cron : fdb085727694e327c8758061a224166b
anacron : 2c15d9bcd208c9446b14452d25d9ca84