- Anwendung/Komponente: JetBrains TeamCity
- Betroffene Version: < 2025.07
- Score (CVSS 3.1): 7.7 High
- Vector: CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:L
- CWEs:CWE-23: Relative Path Traversal
Im Rahmen einer näheren Analyse von JetBrains TeamCity konnte ich eine Schwachstelle finden.
Beschreibung
JetBrains TeamCity erlaubt die Installation zusätzlicher Plugins über ZIP-Dateien. Während der Upload-Mechanismus auf Linux und macOS korrekt vor klassischen Zip-Slip-Angriffen schützt, existiert unter Windows eine kritische Lücke: Durch speziell präparierte Dateipfade mit Backslashes (..\) ist ein beliebiger Datei-Write außerhalb des Plugin-Verzeichnisses möglich – inklusive Überschreiben bereits existierender Dateien.
Das Resultat: Remote Code Execution auf dem TeamCity-Host, ohne dass das Plugin aktiviert werden muss. Der reine Upload reicht aus.
In diesem Beitrag zeige ich die Schwachstelle, den technischen Hintergrund und den Proof-of-Concept-Angriffsweg.
Technischer Hintergrund
TeamCity entpackt hochgeladene Plugin-ZIP-Dateien serverseitig rekursiv. Um Directory Traversal zu verhindern, filtert TeamCity typische Unix-Pfadangaben wie:
../
/../
Diese Filter greifen zuverlässig auf Linux und macOS.
Auf Windows werden Pfade jedoch mit Backslashes (\) interpretiert. Genau hier liegt das Problem:
..\..\..\webapps\ROOT\404.jsp
Diese Pfadangabe wird von der aktuellen Filterlogik nicht erkannt, beim Entpacken aber von der Windows-Dateisystem-API korrekt als Traversal interpretiert.
Damit kann ein Angreifer Dateien beliebig außerhalb des Plugin-Ordners schreiben oder überschreiben – solange der TeamCity-Prozess Schreibrechte besitzt.
Auswirkungen
- Arbitrary File Write auf dem Hostsystem
- Überschreiben bestehender Dateien möglich
- Keine Einschränkung der Dateiendung (.jsp, .exe, .bat, .lnk, …)
- Kein Aktivieren des Plugins erforderlich
- Läuft bei der Windows-Installation TeamCity als SYSTEM → vollständige Systemkompromittierung möglich (JetBrains empfiehlt dies explizit nicht!)
Ein besonders einfacher Angriffsweg ist das Überschreiben einer JSP-Datei im TeamCity-Webroot, um eine Webshell zu platzieren.
Proof of Concept – Angriffskette
1. Erzeugen der bösartigen ZIP-Datei
Die ZIP-Datei muss unter Linux erstellt werden. Python auf Windows normalisiert Backslashes zu Slashes, wodurch der Exploit dort nicht funktioniert.
Beispielhafter Eintrag im ZIP:
..\..\..\webapps\ROOT\404.jsp
Beim Entpacken landet die Datei direkt im TeamCity-Webverzeichnis. In 7-Zip sieht es beispielhaft wie folgt aus:

2. Upload des Plugins
Im TeamCity-Interface wird die ZIP-Datei ganz normal über “Upload plugin zip” hochgeladen.

Wichtig: Das Plugin muss nicht aktiviert werden. Der Entpackvorgang erfolgt bereits beim Upload.
3. Neustart von TeamCity
Nach einem Server-Restart wird die manipulierte Datei aktiv geladen.

In meinem PoC wurde die Standard-404.jsp überschrieben.
4. Triggern der Webshell
Durch Aufruf einer nicht existierenden Seite wird die neue 404.jsp ausgeführt – in meinem Fall eine einfache JSP-Webshell.
Damit ist Remote Code Execution auf dem Host erreicht.

Exploit-Stealth
Ein Angreifer kann den Payload unauffällig in ein legitimes Plugin integrieren, etwa in ein bekanntes Community-Plugin. Da die ZIP-Datei rekursiv entpackt wird, reicht ein einzelner manipulierter Pfadeintrag irgendwo im Archiv.
Ein Administrator erwartet bei einem Plugin-Upload keine direkte Systemmodifikation – was diese Angriffstechnik besonders heimtückisch macht.
Root Cause
Die Filterlogik validiert nur Unix-Pfadseparatoren (/).
Windows-Pfadseparatoren (\) werden nicht korrekt normalisiert oder geprüft.
Mitigation
- Backslashes vor der Pfadprüfung in Slashes normalisieren
- Pfade nach dem Entpacken auf Zielverzeichnis beschränken
- Nutzung sicherer ZIP-Entpacker mit canonical path checks
Da die Lücke ausschließlich Windows betrifft, bleibt Linux/macOS unbeeinflusst.
Hinweis
Alle Tests wurden auf der eigenen, lokalen Instanz durchgeführt sowie mit eigenen, erstellten Test-Nutzerdaten.
JetBrains hat schnell, konstruktiv und professionell reagiert.
Timeline
- Meldung am 13.06.2025 an JetBrains
- Rückmeldung am 13.06.2025
- Fehler behoben am 07.07.2025
- Patch veröffentlicht am 20.07.2025
- CVE-Eintrag am 28.07.2025 mit CVE-2025-54531
- Release des Blog-Eintrages mit Details: 25.01.2026