
Dies ist ein kurzer Bericht über eine Sicherheitslücke (CVE-2019-12489), die beim Herumspielen mit einem Fastgate-Modem/-Router von Fastweb und Ghidra entdeckt wurde. Die Schwachstelle ermöglicht die Ausführung einer Befehlsinjektion über eine HTTP-Anfrage und kann genutzt werden, um eine SSH-Shell zu aktivieren.
Alle Firmware-Dateien befinden sich unter http://59.0.121.191:8080/ACS-server/file/FILENAME
Wobei FILENAME gleich ist:
Um beispielsweise die neueste Firmware zu erhalten, gehen Sie einfach zu http://59.0.121.191:8080/ACS-server/file/0.00.89_FW_200_Askey
Um die Dateien zu extrahieren, benötigen wir das Dienstprogramm unter https://github.com/nlitsme/ubidump (dies ist das erste, das bei mir funktioniert hat).
Ein binwalk auf die Datei liefert uns:
$ binwalk 0.00.89_FW_200_Askey
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
94 0x5E JFFS2 filesystem, little endian
3276894 0x32005E UBI erase count header, version: 1, EC: 0x0, VID header offset: 0x800, data offset: 0x1000
Wir brauchen das JFFS2-Dateisystem nicht, sondern nur den UBI-Teil. Dazu können wir die Datei mit dd zuschneiden.
Dazu benötigen wir die Gesamtgröße und den UBI-Startpunkt.
Die Dateigröße kann mit ls abgerufen werden:
$ ls -la
total 55836
drwxr-xr-x 3 riccardo users 4096 set 24 10:07 .
drwx------ 83 riccardo users 12288 set 24 10:08 ..
-rw-r--r-- 1 riccardo users 57147506 set 24 10:05 0.00.89_FW_200_Askey
Der Wert 57147506 ist der, den wir brauchen.
Wenn wir uns die Ausgabe von binwalk ansehen, sehen wir, dass der UBI-Teil bei 3276894 beginnt. Mit diesen beiden Werten können wir dd wie folgt verwenden:
$ dd if=0.00.89_FW_200_Askey of=0.00.89_FW_200_Askey.UBI bs=1 skip=3276894 count=57147506
Jetzt können wir ubidump verwenden (nach einer anfänglichen Konfiguration, die von der Systemkonfiguration abhängt):
$ git clone https://github.com/nlitsme/ubidump.git
$ sudo pip install crcmod
$ yay -S python-lzo
$ python ubidump/ubidump.py -s bump 0.00.89_FW_200_Askey.UBI
Wir haben nun das Dateisystem in bump/rootfs_ubifs/
Jetzt können wir mit der Analyse etwas weiter fortfahren.
Wenn wir uns im Dateisystem umsehen, sehen wir, dass die Web-GUI von mini_httpd verwaltet wird:
$ grep -i -r "mini_httpd"
etc/sniproxy/urlfilter3.sh:ln -sf /usr/sbin/mini_httpd $URLFILTER_WEBD_PATH
etc/sniproxy/urlfilter3.sh:$URLFILTER_WEBD_PATH -d $URLFILTER_WEB_PATH -c "**.cgi" -u admin -S -E /web/mini_httpd.pem -p $webd_https_port
bin/web.sh:#mv /tmp/mini_httpd /usr/sbin
bin/web.sh:killall -9 mini_httpd
bin/web.sh:mini_httpd -d /web -c "STATUSAPI/**.cgi|STATUSAPI/*" -u admin -T "UTF-8" -p 8080
Und wir sehen, dass mini_httpd von einer .cgi-Datei abhängt:
$ grep -i -r "status.cgi"
web/factory/mtcmd/mt_info.htm: "url":"/status.cgi",
web/fw-router/app/app.js:.value('apiServiceUrl', '/status.cgi')
**web/js/status.js:var CGI_NAME='status.cgi';**
web/js/status.js: "url":"http://192.168.101.93/STATUSAPI/status.cgi",
web/js/status.js: "url":"http://192.168.101.93/STATUSAPI/status.cgi",
web/js/status.js: "url":http://192.168.101.93/STATUSAPI/status.cgi,
Also können wir mit Ghidra beginnen, in die status.cgi zu schauen.
Nachdem wir viele Details übersprungen haben, wird die Schwachstelle unten beschrieben.
Das erste, worauf man achten sollte, ist eine Main-Methode wie die auf diesem Bild:

Wir können sehen, dass setup aufgerufen wird. Nach ein wenig Herumschauen scheint run_service(...) der Kern aller Funktionalitäten zu sein.

Wenn wir nach &service_tab suchen, sehen wir, dass bestimmte Zeichenfolgen mit tatsächlichem Code verbunden sind, der von run_service(...) ausgeführt wird.

Nachdem ich mir diese Methoden nacheinander angesehen habe, stoße ich auf usb_remove

Im Detail:
mountVal = (char *)find_val(httpparams,"mount");
Nimmt die Zeichenfolge aus der URL-Anfrage direkt in eine Variable
sprintf((char *)&mountLocation,"/mnt/%s",mountVal);
Erstellt einen vollständigen Pfad basierend auf dem Parameter in der URL-Anfrage
mountLocation
mountLocation wird direkt in einem Befehl verwendet
Es gibt jedoch Prüfungen, um eine Befehlsinjektion zu verhindern. Insbesondere:
invalidChars = 0x60273b7c;
Wird verwendet, um auf einige ungültige Zeichen wie ` ' ; | zu prüfen, aber & ist nicht in der Liste enthalten. Wenn der Parameter mount also gleich &ping -c 10 192.168.1.172& ist, erlaubt die Prüfung die Ausführung von /statusapi/bin/umount -lf &ping -c 10 192.168.1.172&.
Der mount-Befehl wird fehlschlagen, aber der nachfolgende Ping wird ausgeführt.
Der veröffentlichte Patch vereinfacht den Code, indem die Prüfungen auf Sonderzeichen eliminiert werden und stattdessen einfach überprüft wird, ob der Ordner existiert.

Der Code zum Ausnutzen dieser Schwachstelle und zum Aktivieren von SSH befindet sich in fastwebEnableSSH.py https://github.com/garis/Fastgate/blob/master/fastwebEnableSSH.py