Einführung

Kürzlich wurde bekannt, dass HP DVLabs mindestens zehn Schwachstellen im Belkin N300 Dual-Band Wi-Fi Range Extender (F9K1111) aufgedeckt hat. Als Reaktion darauf hat Belkin die Firmware-Version 1.04.10 veröffentlicht. Da dies das erste Update für den F9K1111 ist und es keine öffentlichen Auslöser für die Schwachstellen gab, hielten wir es für interessant, einen genaueren Blick darauf zu werfen.

Auspacken des Updates

Um unsere Analyse zu beginnen, haben wir das Firmware-Update vom Hersteller heruntergeladen. Zum Entpacken des Updates haben wir ein Firmware-Tool namens binwalk verwendet:

$ binwalk -Me F9K1111_WW_1.04.10_upg.bin

Das Ergebnis ist ein ziemlich normal aussehendes extrahiertes SquashFS-Dateisystem, das das Stammverzeichnis des Geräts darstellt (siehe unten).

Screenshot der binwalk SquashFS-Dateisystemextraktion, die das Stammverzeichnis des Geräts darstellt

Um nun den Bindiff durchzuführen, müssen wir ein wenig mit der Hardware interagieren, um die Dateien in den vorbereiteten Zustand zu versetzen.

Abrufen der Basis-Firmware

Um die Basis-Firmware zu analysieren, benötigen wir eine Möglichkeit, die Daten aus dem physischen Gerät auszulesen. Dazu müssen wir zunächst das Gerät aus seinem Gehäuse entfernen.

Belkin F9K1111 Firmware aus dem Gehäuse entfernt

Rot und blau hervorgehoben sind mögliche Wege zum Abrufen der Firmware, der SPI-Flash-Chip bzw. die UART-Schnittstelle. Obwohl wir eine gewisse Aktivität auf dem UART gesehen haben, werden wir mit der Analyse des Basis-Images auf dem SPI-Flash-Chip fortfahren. Die Pinbelegung des Chips, mit dem wir es zu tun haben, MX25L1606e, ist von Macronix leicht erhältlich.

Macronix MX25L1606e Pin-Konfigurationen

Nachdem wir uns dieses Blatt geschnappt und den Chip entfernt haben, können wir unseren GoodFET entsprechend der obigen generischen 8-poligen Pinbelegung verdrahten.

Nachdem wir die Pins 7 und 8 gebrückt haben, überprüfen wir, ob alles richtig angeschlossen ist mit

$ python goodfet.spiflash info

Als nächstes können wir goodfet.spiflash dump ausführen, um den Inhalt des Chips zu erhalten.

$ python goodfet.spiflash dump s

Bildschirmfoto des goodfet.spiflash-Dumps

Abschließend können wir die resultierende Datei einer kurzen Prüfung unterziehen, um sicherzustellen, dass der Dump korrekt aussieht (d. h. zumindest einige lesbare Zeichenfolgen enthält).

Bildschirmfoto der resultierenden Datei, um sicherzustellen, dass der Dump echt aussieht

Die resultierende Binärdatei kann wie bisher mit binwalk entpackt werden.

Diffing das Update

Wenn man die beiden entpackten Dateisysteme auf einen Windows-Rechner überträgt und in WinMerge ablegt, sieht man, dass sich nicht viel geändert hat.

Bildschirmfoto von WinMerge

Die Dateien compiler_data, version und FUNCTION_SCRIPT enthalten keine interessanten Änderungen (außer vielleicht für einige Daten, die für das Fingerprinting nützlich sein könnten). Auch die Änderung an util_system.asp ist nicht besonders interessant. Wir werden uns also im Wesentlichen die Änderungen von Belkin an webs, dem GoAhead Webserver, ansehen.

Analyse der Bahnen

Die HP-Initiative Zero Day hat die Schwachstellen mit den Namen der offenbar betroffenen Funktionen oder Eingaben benannt. Sie lauten wie folgt:

  • formWpsStart pinCode Remote CodeExecution-Schwachstelle
  • formWlanSetupWPS wps_enrolee_pin Sicherheitslücke bei Remotecodeausführung
  • formWlanMP Sicherheitslücke bei der Remotecodeausführung
  • formBSSetSitesurvey Sicherheitslücke bei der Remotecodeausführung
  • formHwSet Sicherheitslücke bei der Remotecodeausführung
  • formConnectionSetting Sicherheitslücke bei der Remote-Code-Ausführung
  • formAccept Sicherheitslücke bei der Remotecodeausführung
  • formiNICWpsStart Sicherheitslücke bei der Remote-Code-Ausführung
  • formUSBStorage Sicherheitslücke bei der Remotecodeausführung

Nachdem wir also die gepatchte Version von webs in IDA geladen hatten, suchten wir in der Liste der Funktionen nach formHwSet und fanden nichts. In der Tat wurden viele dieser Funktionen nicht gefunden. Wenn wir Bindiff aufrufen, können wir sehen, dass 7 Funktionen während des Updates entfernt wurden:

Bildschirmfoto der Liste der Funktionen

Diese stimmen gut mit den Daten aus dem ZDI-Bulletin überein. Tatsächlich wurden alle in den ZDI-Hinweisen aufgeführten Funktionen mit Ausnahme von formWlanSetupWPS und formBSSetSitesurvey entfernt. Schauen wir uns die entfernten Funktionen einmal genauer an.

formUsbStorage

Die erste Funktion, die wir betrachten, ist formUsbStorage. Nachdem wir die Funktion kurz gelesen haben, ist das Problem ziemlich offensichtlich. Die POST-Variable sub_dir, auf die über die GoAhead-Webs-API-Funktion websGetVar zugegriffen wird, wird dann in einem Aufruf an system verwendet, was eine Befehlsinjektion ermöglicht.

Bildschirmfoto von formUsbStorage

Dieser Code könnte über ausgelöst werden:

wget --post-data="sub_dir=vectra;reboot" http://belkin.range/goform/formUSBStorage

formWlanMP

Ein ähnlicher Fehler ist im Formular actionformWlanMP zu finden. Verfolgt man die Aufrufe von websGetVar, ergeben sich einige Möglichkeiten.

Screenshot eines in actionformWlanMP gefundenen Fehlers

Im Folgenden sehen wir, dass diese wenigen Möglichkeiten alle als Wege zur Injektion in den Systemaufruf funktionieren - wir haben uns für ateFunc entschieden.

Screenshot eines in ateFunc gefundenen Fehlers

Dieser Code könnte über ausgelöst werden:

wget --post-data="ateFunc=;reboot;" http://belkin.range/goform/formWlanMP

formHwSet

Hier gibt es eine weitere Befehlsinjektion, dieses Mal verwenden wir die Variable [sic] Anntena.

Screenshot der Anntena-Variableninjektion im Befehl

Dieser Code könnte über ausgelöst werden:

wget --post-data="Anntena=;reboot;" http://belkin.range/goform/formHwSet

formConnectionSetting

Hier haben wir eine Befehlsinjektion im Parameter timeOut in der Funktion formConnectionSetting.

Bildschirmfoto der Befehlsinjektion in den timeOut-Parameter in der Funktion formConnectionSetting

Dieser Code könnte über ausgelöst werden:

wget --post-data="timeOut=1;reboot;" http://belkin.range/goform/formConnectionSetting

formBSSetSitesurvey

An diesem Punkt haben wir das Pferd der gelöschten Funktionen totgeschlagen. Werfen wir einen Blick auf die wichtigere der Funktionen, die Belkin nicht gelöscht hat - formBSSetSitesurvey. Hier ist ein Überblick:

formBSSetSitesurvey Überblick

Nachdem wir entsetzt zurückgeschreckt sind, können wir heranzoomen und sehen, dass die wichtigste Änderung darin besteht, dass Belkin eine Funktion namens strcat_escape hinzugefügt hat, die in dieser Funktion für Quellen aus websGetVar verwendet wird.

Belkin hat eine Funktion namens strcat_escape hinzugefügt

This strcat_escape function takes 3 buffers - dst, src, and tokens. The function uses nested loops to search the src string for existence of any of the tokens to be escaped, if found they are escaped before being copied into dst. In the pictured case token_of_none_quotation is passed as tokens which is defined as"\\\"'$()<>` #&*

Wir haben diese Funktion in C aus dem Web-Binary neu implementiert und können die erwartete Ausgabe sehen:

Ausgabe der Funktion in webs binary

Diese (vermutlich korrekt) escapte Zeichenkette wird dann wie gewohnt über sprintf an das System übergeben.

Bildschirmfoto sprintf-Funktion

Die Wirksamkeit dieses Pflasters hängt von einigen Faktoren ab:

  • Die Funktion strcat_escape funktioniert vollständig wie vorgesehen
  • strcat_escape verursacht nicht ungewollt Pufferüberläufe ;-)
  • strcat_escape wird für alle Benutzereingaben verwendet, die im System landen
  • Wir haben uns mit Belkin wegen einiger dieser Punkte in Verbindung gesetzt.

Schlussfolgerung

Wir alle wissen bereits, dass die Sicherheitsreife von eingebettetem Gerätecode ein Problem darstellt. Hier sehen wir, dass selbst bei Geräten, die 2014 veröffentlicht wurden, dies ein Problem bleibt.