
Offenlegung und PoC für eine Root-Datei-Lese-/Schreibschwachstelle im Debug-Kanal des TP-Link Deco XE75 Pro V3 (tmpsvr-Opcodes 0xC456/0xF0), mit CVSS-Analyse und Handler-Dekompilierung.
Begleitendes VLAN-Projekt: experimentelle Fixed-VLAN-30-Quellcode-Alpha für das exakte XE75 Pro V3 Firmware/Profil. Es erfordert vom Betreiber bereitgestellte Originaldateien und verfügt über keinen allgemeinen Installer oder flashbares Image. Gast-VLAN 591 bleibt ungelöst; die abschließende Abnahme mit drei Einheiten (Kaltstart, UI und Client-Isolation) ist unvollständig. Siehe aktueller Status.
Forschungsoffenlegung, TP-Link Deco XE75 Pro V3, Firmware 1.5.0 Build
20260603 Rel.15804. Erstellt für [email protected] und zur öffentlichen Veröffentlichung zusammen mit unserer 802.1Q-IoT-VLAN-Implementierung (deco-iot-vlan).
Der eigentümerauthentifizierte Debug-SSH-Kanal des Deco (Dropbear auf TCP 20001,
nur direct-tcpip-Weiterleitung, Passwort-Authentifizierung) erreicht einen internen
tmpsvr-Dienst auf 127.0.0.1:20002. Einer seiner Lua-Handler,
inner_file_push (Opcode 0xC456), öffnet params.file im Modus "w" und
schreibt params.content unverändert als root, ohne Pfad-Allowlist, ohne Größen-
beschränkung und ohne Privilegienabgabe. Ein verwandter Opcode (0xF0) bietet ein
passendes Root-Dateilesen. Zusammen: authentifiziertes Lesen + Schreiben des gesamten
Root-Dateisystems, was auf einem Router das gesamte Gerät bedeutet.
SSH :20001 (username = SHA1(owner_email), password = TP-Link account password)
-> direct-tcpip -> 127.0.0.1:20002 (TMPv2)
-> 0xC456 inner_file_push : io.open(file,"w"); write(content); close() [root]
-> 0x00F0 root file read : byte-exact file read [root]
/etc/config ist ein beschreibbares Live-ramfs → ändere einen Schlüssel, der Router übernimmt ihn./www wird über HTTPS von uhttpd ausgeliefert → hochgeladene Dateien sind sofort erreichbar./tp_data/user_data ist persistenter ubifs-Flash → übersteht einen Neustart.GET /cgi-bin/luci → Root-Lua-Ausführung → io.popen → Ausführung beliebiger
Root-Binärdateien.Alle vier Schritte wurden auf dem eigenen Hauptgerät des Eigentümers ausgeführt und rückgängig gemacht.
tmpsvr zwei Jahre nach CCS'24 / Black Hat '24 noch immer nicht behoben istDas UCR-SecLab-Team hat den Debug-Kanal :20001 -> 127.0.0.1:20002 (tmpsvr) vor zwei Jahren öffentlich dokumentiert, in CCS 2024 — „Untangling the Knot: Breaking Access Control in Home Wireless Mesh Networks" (sowie Black Hat USA 2024 — „Fallen Tower of Babel"). Ihr Einstiegspunkt bei älteren Deco-Modellen (X55, FW 1.2.2) war das Faktorisieren von 512-Bit-RSA-Hostkeys und das Ausnutzen unvalidierter tmpsvr-Handler.
Beobachtete Unterschiede und verbleibende Handler auf genau dieser Firmware:
ssh-rsa-Hostkeys von 512 Bit auf 2048 Bit erhöht (ein gemeinsamer beobachteter Schlüssel über alle drei Mesh-Einheiten, SHA256:9feb3ac4...932a36, plus ecdsa-sha2-nistp521 pro Einheit), wodurch der 512-Bit-Faktorisierungspfad aus dem Vortrag von 2024 geschlossen wurde.1.5.0 vorhanden:
:20001 (svr_auth_uci) bleibt aktiv und verwendet SHA1(owner_email) + das gemeinsame TP-Link-ID-Passwort.0xC456 (inner_file_push) öffnet weiterhin jeden vom Aufrufer angegebenen Pfad im Modus "w" als root ohne jegliche Pfadvalidierung.0x00F0 liest weiterhin jede Datei im Dateisystem als root.0xC505 (tty2tcp/start) — der exakt unquotierte /bin/sh -c-Command-Injection-Handler, der im Paper von 2024 hervorgehoben wurde — steckt noch immer in der Firmware vom Juni 2026 (1.5.0) und ist vollständig unbehoben.luci/controller/admin/mobile_app/iot_device,
inner_file_push).Nur die LAN-Erreichbarkeit wurde nachgewiesen. Für das beobachtete LAN-only-Profil verwenden wir die AV:A-Varianten: v3.1 6.8 / v4.0 8.5. Die AV:N-Werte unten sind bedingt durch einen nachgewiesenen Netzwerkpfad; die Cloud-Erreichbarkeit ist unbestätigt.
Dies ist eine Post-Authentifizierungs-Eskalation zu Root mit Eigentümerrechten — kein
Unauth-RCE — die Werte für das beobachtete Profil unten sind 6.8 (v3.1) und 8.5 (v4.0). Die vollständige Begründung und die
verworfenen Aufwertungen finden sich in docs/cvss-analysis.md.
CVSS v3.1 — LAN-only-Bewertung 6.8 (Mittel); bedingte Remote-Variante 7.2 (Hoch):
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H = 7.2 (High)
CVSS:3.1/AV:A/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H = 6.8 (Medium) # if LAN-only
Entscheidende Bewertungen: PR:H (der Eigentümer / TP-Link-ID-Account ist der administrative
Prinzipal des Geräts) und S:U (der Handler läuft bereits als root — es wird keine
Autoritätsgrenze überschritten). Ein früherer Entwurf wurde mit 9.9 über PR:L + S:C bewertet;
beide werden verworfen.
CVSS v4.0 — Bewertung nur für LAN 8.5 (High); bedingte Remote-Variante 8.6 (High):
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N = 8.6 (High)
CVSS:4.0/AV:A/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N = 8.5 (High) # if LAN-only
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L = 9.3 (Critical) # with Subsequent-System LAN/mesh impact
Das reale Risiko – ein gestohlenes/weiterverwendetes TP-Link-ID-Passwort, das sich in persistentes Root über das gesamte Mesh hinweg verwandelt, plus Client-Traffic-MITM – gehört in die Erzählung (und in die v4.0-Metriken SC:H/SI:H/SA:L für Subsequent-System), nicht in einen aufgeblähten v3.1-Basisvektor.
poc/deco_filepush_poc.py – eigenständig (stdlib + paramiko). Anmeldedaten
ausschließlich über die Umgebungsvariablen DECO_EMAIL / DECO_PASSWORD. Live-Modi erfordern
DECO_HOSTKEY, unabhängig verifiziert: rohes Base64, eine Public-Key-Zeile oder eine
ssh-keyscan-Schlüsselzeile (Kommentare werden unterstützt). Ein Scan allein authentifiziert
das Gerät nicht. Die HTTPS-Prüfung vergleicht die ausgelieferten Bytes, verifiziert jedoch nicht dessen Zertifikat.
Genau ein Modus ist erforderlich; eine fehlgeschlagene Verifikation endet mit einem Exit-Code ungleich null.
python3 poc/deco_filepush_poc.py --selftest # offline framing sanity
[email protected] DECO_PASSWORD=*** DECO_HOSTKEY="$TRUSTED_DECO_HOSTKEY" \
python3 poc/deco_filepush_poc.py --run # write marker + readback + HTTPS check
[email protected] DECO_PASSWORD=*** DECO_HOSTKEY="$TRUSTED_DECO_HOSTKEY" \
python3 poc/deco_filepush_poc.py --cleanup <nonce> # overwrite marker with empty content
Der PoC schreibt einen einzelnen inerten Marker nach /www/log_export (ramfs; wird auch beim Neustart gelöscht) und erfordert dann einen byte-genauen Rücklesevorgang über den eigenen Root-Read-Opcode des Geräts sowie eine unveränderte HTTPS-Bereitstellung, bevor Erfolg gemeldet wird.