
Divulgazione e PoC per una vulnerabilità di lettura/scrittura di file con privilegi di root nel canale di debug del TP-Link Deco XE75 Pro V3 (opcode tmpsvr 0xC456/0xF0), con analisi CVSS e decompilazione dell'handler.
Progetto VLAN complementare: sorgente alpha sperimentale con VLAN 30 fissa per lo specifico firmware/profilo XE75 Pro V3. Richiede file stock forniti dall'operatore e non dispone di un installer generale né di un'immagine flashabile. La VLAN guest 591 resta irrisolta; il collaudo finale di accettazione su tre unità (cold-boot, UI e isolamento client) è incompleto. Vedi stato attuale.
Divulgazione di ricerca, TP-Link Deco XE75 Pro V3, firmware 1.5.0 Build
20260603 Rel.15804. Preparata per [email protected] e per il rilascio pubblico insieme alla nostra implementazione VLAN IoT 802.1Q (deco-iot-vlan).
Il canale SSH di debug autenticato dal proprietario del Deco (Dropbear su TCP 20001,
solo inoltro direct-tcpip, autenticazione con password) raggiunge un servizio
tmpsvr interno su 127.0.0.1:20002. Uno dei suoi handler Lua,
inner_file_push (opcode 0xC456), apre params.file in modalità "w" e
scrive params.content verbatim come root, senza allowlist di percorsi, senza limite
di dimensione e senza riduzione dei privilegi. Un opcode affine (0xF0) fornisce una
lettura di file come root corrispondente. Insieme: lettura + scrittura autenticate dell'intero
filesystem root, che su un router equivale all'intero dispositivo.
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 è un ramfs scrivibile attivo → modifica una chiave, il router la rispetta./www è servito via HTTPS da uhttpd → i file caricati sono immediatamente raggiungibili./tp_data/user_data è una flash ubifs persistente → sopravvive al riavvio.GET /cgi-bin/luci → esecuzione di Lua come root → io.popen → esecuzione arbitraria di
binari come root.Tutti e quattro i passaggi sono stati eseguiti e ripristinati sull'unità principale di proprietà del titolare.
tmpsvr è ancora non corretto 2 anni dopo CCS'24 / Black Hat '24Il team UCR SecLab ha documentato pubblicamente il canale di debug :20001 -> 127.0.0.1:20002 (tmpsvr) due anni fa in CCS 2024 — "Untangling the Knot: Breaking Access Control in Home Wireless Mesh Networks" (e Black Hat USA 2024 — "Fallen Tower of Babel"). Il loro punto di ingresso sui modelli Deco più vecchi (X55, FW 1.2.2) era la fattorizzazione delle hostkey RSA a 512 bit e l'abuso di handler tmpsvr non validati.
Differenze osservate e handler rimanenti su questo firmware esatto:
ssh-rsa da 512 bit a 2048 bit (una chiave condivisa osservata su tutte e tre le unità mesh, SHA256:9feb3ac4...932a36, più ecdsa-sha2-nistp521 per unità), chiudendo il percorso di fattorizzazione a 512 bit del talk del 2024.1.5.0:
:20001 (svr_auth_uci) rimane attiva usando SHA1(owner_email) + la password condivisa dell'ID TP-Link.0xC456 (inner_file_push) apre ancora qualsiasi percorso fornito dal chiamante in modalità "w" come root senza alcuna validazione del percorso.0x00F0 legge ancora qualsiasi file sul filesystem come root.0xC505 (tty2tcp/start) — l'esatto handler di command-injection /bin/sh -c senza quoting evidenziato nel paper del 2024 — è ancora presente nel firmware di giugno 2026 (1.5.0) completamente non corretto.luci/controller/admin/mobile_app/iot_device,
inner_file_push).È stata dimostrata solo la raggiungibilità dalla LAN. Per il profilo osservato solo-LAN usiamo le varianti AV:A: v3.1 6.8 / v4.0 8.5. I punteggi AV:N riportati di seguito sono condizionati a un percorso di rete dimostrato; la raggiungibilità dal cloud non è verificata.
Questa è un'escalation a root post-autenticazione, con privilegi del proprietario — non una
RCE non autenticata — i punteggi del profilo osservato riportati di seguito sono 6.8 (v3.1) e 8.5 (v4.0). La motivazione completa e le
inflazioni rifiutate sono in docs/cvss-analysis.md.
CVSS v3.1 — valutazione solo-LAN 6.8 (Medio); variante remota condizionale 7.2 (Alto):
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
Chiamate decisive: PR:H (il proprietario / account TP-Link-ID è il principale amministrativo del dispositivo) e S:U (l'handler è già in esecuzione come root — nessun confine di autorità viene attraversato). Una bozza precedente assegnava 9.9 tramite PR:L + S:C; entrambe vengono respinte.
CVSS v4.0 — valutazione solo LAN 8.5 (High); variante remota condizionale 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
Il rischio nel mondo reale — una password TP-Link-ID rubata/riutilizzata che si converte in root persistente sull'intera mesh, più MITM sul traffico dei client — appartiene alla narrativa (e alle metriche Subsequent-System SC:H/SI:H/SA:L della v4.0), non a un vettore base v3.1 gonfiato.
poc/deco_filepush_poc.py — autonomo (stdlib + paramiko). Credenziali
solo tramite le variabili d'ambiente DECO_EMAIL / DECO_PASSWORD. Le modalità live richiedono
DECO_HOSTKEY, verificata in modo indipendente: base64 grezzo, una riga di chiave pubblica, o una
riga di chiave da ssh-keyscan (commenti supportati). Una scansione da sola non autentica
il dispositivo. Il controllo HTTPS confronta i byte serviti ma non verifica il suo certificato.
È richiesta esattamente una modalità; una verifica fallita termina con codice diverso da zero.
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
Il PoC scrive un singolo marcatore inerte in /www/log_export (ramfs; cancellato anche al riavvio), poi richiede una rilettura byte-exact tramite l'opcode di lettura root del dispositivo stesso e un servizio HTTPS non modificato prima di segnalare il successo.