靶机信息:
- IP 地址: 10.10.11.55
- 目标: 获取 user.txt 和 root.txt
一、 信息收集与初始探测
1. 端口扫描 (Nmap)
首先使用 Nmap 对目标进行端口扫描,了解开放的服务:

扫描结果显示开放了 22 (SSH) 和 80 (HTTP) 端口。HTTP 服务返回 302 重定向,指向域名 http://titanic.htb/。
2. 配置 Hosts 文件
为了正常访问 Web 服务,我们需要将域名和 IP 地址添加到本地 hosts 文件。
1 | 10.10.11.55 titanic.htb |

3. 访问 Web 服务
配置好 hosts 文件后,在浏览器中访问 http://titanic.htb/。看到了一个关于泰坦尼克号邮轮预订的网站。

网站底部有一个预订信息的提交表单:

二、 Web 应用枚举与漏洞发现
1. 技术栈识别 (WhatWeb)
使用 whatweb 识别网站使用的技术:
1 | whatweb http://titanic.htb/ |

关键信息:
- 后端:Werkzeug/3.0.3 (Python Web 框架)
- Python 版本:3.10.12
- 前端:Bootstrap, JQuery
2. 目录与子域名扫描
使用 dirsearch 扫描目录,但未发现有价值的信息(大多是 40x 错误)。

接着,使用 gobuster 结合子域名字典进行子域名爆破:

扫描发现了一个子域名 dev.titanic.htb。将其添加到 hosts 文件:
1 | 10.10.11.55 titanic.htb dev.titanic.htb |
3. 表单提交与路径遍历漏洞
回到主站 http://titanic.htb/,尝试提交预订表单,并使用 Burp Suite 拦截请求和响应。
提交表单后,服务器返回一个 302 重定向,指向一个下载链接,格式为 /download?ticket=UUID.json。

这个 ticket 参数看起来很可疑。尝试利用它进行路径遍历,读取服务器上的敏感文件。我们尝试读取 /etc/passwd:
修改 Burp Repeater 中的请求,将 /download?ticket=UUID.json 改为 /download?ticket=../../../../../../etc/passwd。

成功读取!这确认了路径遍历漏洞的存在。在 /etc/passwd 中,我们注意到了 developer 用户。
三、 利用路径遍历深入挖掘
1. 探索开发环境 (dev.titanic.htb)
访问之前发现的子域名 http://dev.titanic.htb/。

页面显示这是一个 Gitea 服务(一个自托管的 Git 服务),然后转向左上角探索,可以看到代码仓库。
查看到 docker-compose.yml 的配置片段。
1 | volumes: |
这表明 Gitea 容器的 /data 目录映射到了宿主机的 /home/developer/gitea/data 目录。
2. 读取 Gitea 配置文件
Gitea 的默认配置文件通常位于 /etc/gitea/conf/app.ini 或其数据目录下的 gitea/conf/app.ini。结合上面发现的 Volume 映射,我们可以推断出宿主机上配置文件的实际路径可能是 /home/developer/gitea/data/gitea/conf/app.ini。

3. 分析配置文件,定位数据库
利用之前发现的路径遍历漏洞,尝试读取这个文件:
在 app.ini 文件中,我们找到了数据库的配置信息:
1 | [database] |


关键信息:
- 数据库类型:SQLite3
- 数据库文件路径 (容器内):
/data/gitea/gitea.db
结合之前的 Volume 映射 (/home/developer/gitea/data:/data),我们可以确定数据库文件在宿主机上的绝对路径为:/home/developer/gitea/data/gitea/gitea.db。
四、 获取用户权限 (User Flag)
1. 下载 Gitea 数据库
既然知道了数据库文件的绝对路径,我们可以再次利用路径遍历漏洞将其下载到本地进行分析:

2. 分析数据库,提取密码哈希
使用 SQLite 客户端打开下载的 gitea.db 文件,查找用户表(通常是 user 表)。


找到了 developer 用户的密码哈希和对应的盐值 (Salt):
- 用户: developer
- 哈希 (passwd):
e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56 - 盐 (salt):
8bf3e3452b78544f8bee9400d6936d34(需要注意,数据库中存储的是 Hex 编码的字符串,使用时需要解码为 bytes)
Gitea 通常使用 PBKDF2-HMAC-SHA256 算法来存储密码哈希。需要破解这个哈希来获取 developer 用户的明文密码。
3. 破解密码哈希
可以使用 Hashcat 或者编写一个简单的 Python 脚本来尝试破解。使用 hashlib.pbkdf2_hmac 结合字典进行爆破。Gitea 的默认迭代次数通常较高(如 50000),需要在破解时指定正确的参数。
准备字典: 将使用常见的 rockyou.txt 字典。
Python 破解脚本 (crack_gitea.py):
1 | import hashlib |
运行脚本进行破解:
1 | python crack_gitea.py |

脚本成功找到了密码!
- 用户名: developer
- 密码: 25282528
4. SSH 登录并获取 User Flag
现在我们拥有了 developer 用户的凭据,可以通过 SSH 登录目标机器:
1 | ssh developer@titanic.htb |
登录成功后,查找并读取 user.txt 文件:

成功获取 User Flag!
五、 权限提升 (Root Flag)
获取了普通用户权限后,下一步是寻找提权到 root 的方法。
1. 本地枚举
在 developer 用户下进行枚举,寻找潜在的提权向量。检查 sudo -l、SUID 文件、计划任务 (cron jobs)、系统服务配置、可写目录和可执行脚本等。
-
sudo -l:developer用户无法免密执行任何 sudo 命令。 -
查找可执行脚本和可写目录:
1
2
3
4
5
6
7
8
9# 查找 /opt 目录下用户可执行的文件
developer@titanic:~$ find /opt -type f -perm -u=x 2>/dev/null
/opt/scripts/identify_images.sh
/opt/app/app.py
# 查找 /opt 目录下用户可写的目录
developer@titanic:~$ find /opt -writable -type d 2>/dev/null
/opt/app/static/assets/images
/opt/app/tickets


我们发现了一个可执行脚本 /opt/scripts/identify_images.sh 和一个用户可写的目录 /opt/app/static/assets/images。这值得深入研究。
2. 分析可疑脚本
查看 /opt/scripts/identify_images.sh 的内容:

脚本的关键行为:
cd /opt/app/static/assets/images: 切换工作目录到我们可写的目录!- 执行
/usr/bin/magick identify命令处理该目录下的.jpg文件。
如果这个脚本是由 root 用户定期运行(例如通过 cron),并且 magick 命令存在某种漏洞,我们就有机会利用可写目录来执行代码。
3. 检查 ImageMagick 版本并查找漏洞
查看 /usr/bin/magick 的版本:

版本为 ImageMagick 7.1.1-35。搜索该版本的漏洞,发现一个相关的 CVE 或安全公告:GHSA-8rxc-922v-phg8。
这个漏洞与 ImageMagick 的 AppImage 打包有关。其 AppRun 启动脚本在设置某些环境变量(如 LD_PRELOAD, LD_LIBRARY_PATH 或 MAGICK_CONFIGURE_PATH)时,会查找并加载当前工作目录下的某些配置文件或库文件。
漏洞利用思路:
/opt/scripts/identify_images.sh脚本首先cd进入了我们可写的目录/opt/app/static/assets/images。- 然后,脚本以其执行者(推测是 root)的权限执行
/usr/bin/magick identify。 - 由于
magick是一个 AppImage 打包的程序 (或其启动脚本存在类似行为),它在启动时会检查当前工作目录(也就是我们可写的/opt/app/static/assets/images)是否存在特定的库文件。 - 如果我们在这个可写目录下放置一个精心构造的、与 ImageMagick 期望加载的库同名的恶意共享库(
.so文件),那么magick命令在执行时就会加载并执行我们库中的代码。 - 利用 C 语言的
__attribute__((constructor))特性,可以在共享库被加载时自动执行我们定义的函数(Payload)。
4. 制作并部署恶意共享库
a. 编写恶意 C 代码 (exploit.c):
创建一个 C 文件,包含我们的 payload。Payload 的目标是将 /root/root.txt 文件复制到我们可访问的目录 /opt/app/static/assets/images/ 并修改其权限,以便我们能读取它。
1 |
|
b. 编译共享库:
在你的攻击机或目标机器上(如果目标机器上有 gcc),使用 gcc 将 C 代码编译成共享库。根据漏洞 PoC 或常见实践,我们可以尝试使用 ImageMagick 可能加载的库名,例如 libxcb.so.1。
将编译好的 libxcb.so.1 文件放置到目标脚本的工作目录,也就是我们可写的 /opt/app/static/assets/images/ 目录下。
1 | gcc -shared -fPIC -o ./libxcb.so.1 exploit.c |
5. 等待触发与获取 Root Flag
现在,我们只需要等待 /opt/scripts/identify_images.sh 脚本被执行。这个脚本很可能是通过 root 用户的 Cron 任务定时运行的(例如,每隔几分钟)。
当脚本运行时:
- 它会
cd到/opt/app/static/assets/images/。 - 它会以
root权限执行/usr/bin/magick identify。 magick进程启动时,会查找并加载当前目录下的libxcb.so.1。- 我们恶意库中的
run_payload函数被执行。 /root/root.txt文件被复制到/opt/app/static/assets/images/root.txt,并且权限被设置为777。
等待一小段时间(可能需要几分钟),然后检查 /opt/app/static/assets/images/ 目录:
1 | developer@titanic:/opt/app/static/assets/images$ ls -l |

成功获取 Root Flag!
六、 总结
- 初始 foothold: 通过 Nmap 发现重定向,配置 hosts 文件访问 Web 服务。
- Web 漏洞: 利用预订表单后的
/download功能存在的路径遍历漏洞,读取了敏感文件。 - 信息泄露: 通过路径遍历读取了
dev子域 Gitea 服务的配置文件 (app.ini) 和 SQLite 数据库 (gitea.db)。 - 密码破解: 从数据库中提取了
developer用户的 PBKDF2 哈希和盐值,并使用字典爆破得到明文密码。 - 获取用户权限: 使用破解的凭据 SSH 登录
developer用户,获得 user flag。 - 权限提升: 分析发现一个由 root 运行的脚本 (
identify_images.sh) 会在用户可写目录下执行 ImageMagick (magick)。利用 ImageMagick AppImage 的库加载漏洞 (GHSA-8rxc-922v-phg8),通过放置恶意共享库 (.so文件) 在脚本的工作目录,实现了代码执行,最终获取了 root flag。
七、 防护与缓解措施
-
修复路径遍历漏洞 (
/download):- 对用户输入进行严格过滤,禁止路径遍历字符 (
../)。 - 在访问文件前,确保请求的路径位于授权的目录下。
- 对用户输入进行严格过滤,禁止路径遍历字符 (
-
保护敏感文件:
- 修复导致文件泄露的根源漏洞(如路径遍历)。
- 遵循最小权限原则,确保 Web 应用进程无权访问 Gitea 等其他服务的配置文件和数据。
-
强化身份验证:
- 强制使用强密码策略,增加密码破解难度。
- 考虑为 Gitea 等关键服务启用双因素认证 (2FA)。
-
安全配置计划任务与脚本:
- 避免让以高权限运行的脚本(如 Cron 任务)在用户可写的目录下执行外部命令。
- 如果必须在特定目录执行,确保所调用的程序(如 ImageMagick)已更新至最新版本,并已修复已知的库加载或命令注入漏洞。
- 定期审计系统上的 SUID/SGID 文件、计划任务和不安全的服务配置。