Belkin F9K1111 V1.04.10 Analyse du micrologiciel

19 août 2015
Vectra AI Security Research team
Cybersécurité
Belkin F9K1111 V1.04.10 Analyse du micrologiciel

Introduction

Récemment, nous avons appris que HP DVLabs avait découvert au moins dix vulnérabilités dans le Belkin N300 Dual-Band Wi-Fi Range Extender (F9K1111). En réponse à cette découverte, Belkin a publié la version 1.04.10 du micrologiciel. Comme il s'agit de la première mise à jour publiée pour le F9K1111 et qu'il n'y a pas eu de déclencheurs publics pour les vulnérabilités, nous avons pensé qu'il serait intéressant d'y jeter un coup d'œil plus approfondi.

Déballage de la mise à jour

Pour commencer notre analyse, nous avons téléchargé la mise à jour du micrologiciel auprès du fournisseur. Nous avons utilisé un outil de microprogrammation appelé binwalk pour décompresser la mise à jour :

binwalk -Me F9K1111_WW_1.04.10_upg.bin

Le résultat est un système de fichiers SquashFS extrait, d'apparence assez standard, représentant la racine de l'appareil, comme on peut le voir ci-dessous.

Capture d'écran de l'extraction du système de fichiers SquashFS de binwalk représentant la racine de l'appareil

Maintenant, pour effectuer le bindiff, nous devons interagir avec le matériel pour mettre les fichiers dans leur état pré-patché.

Obtenir le micrologiciel de base

Pour analyser le micrologiciel de base, nous avons besoin d'un moyen pour extraire les données de l'appareil physique. Pour ce faire, nous devons d'abord retirer l'appareil de son boîtier.

Firmware Belkin F9K1111 retiré de son boîtier

En rouge et en bleu, nous voyons les voies possibles pour récupérer le micrologiciel, la puce flash SPI et l'interface UART, respectivement. Bien que nous ayons constaté un certain niveau d'activité sur l'UART, nous allons procéder à l'analyse de l'image de base sur la puce flash SPI. Le brochage de la puce que nous utilisons, MX25L1606e, est facilement disponible auprès de Macronix.

Configuration des broches du MX25L1606e de Macronix

Après avoir pris cette feuille et retiré la puce, nous sommes prêts à câbler notre GoodFET en respectant le brochage générique à 8 broches ci-dessus.

Après avoir relié les broches 7 et 8, nous vérifions que tout est correctement branché à l'aide de la fonction

$ python goodfet.spiflash info

Ensuite, nous pouvons exécuter goodfet.spiflash dump pour obtenir le contenu de la puce.

$ python goodfet.spiflash dump s

capture d'écran du dumping de goodfet.spiflash

Enfin, nous pouvons effectuer un rapide contrôle sur le fichier résultant pour nous assurer que le dump est correct (c'est-à-dire qu'il contient au moins quelques chaînes lisibles).

capture d'écran du fichier résultant pour s'assurer que le dump semble légitime

Le fichier binaire qui en résulte peut être décompressé via binwalk comme précédemment.

Diffusion de la mise à jour

En déplaçant les deux systèmes de fichiers décompressés sur une machine Windows et en les plaçant dans WinMerge, nous pouvons constater que peu de choses ont changé.

capture d'écran de WinMerge

Les fichiers compiler_data, version et FUNCTION_SCRIPT ne contiennent pas de changements intéressants (à part peut-être quelques données qui pourraient être utiles pour le fingerprinting). La modification du fichier util_system.asp n'est pas non plus très intéressante. Nous allons donc nous pencher sur les modifications apportées par Belkin à webs, le GoAhead Webserver.

Analyse des toiles

L'initiative Zero Day de HP a nommé les vulnérabilités avec ce qui semble être des noms de fonctions ou des entrées affectées. Il s'agit des noms suivants :

  • Vulnérabilité d'exécution de code à distance dans formWpsStart pinCode
  • formWlanSetupWPS wps_enrolee_pin Vulnérabilité d'exécution de code à distance
  • Vulnérabilité d'exécution de code à distance de formWlanMP
  • Vulnérabilité d'exécution de code à distance de formBSSetSitesurvey
  • Vulnérabilité d'exécution de code à distance de formHwSet
  • Vulnérabilité d'exécution de code à distance de formConnectionSetting
  • Vulnérabilité d'exécution de code à distance de formAccept
  • Vulnérabilité d'exécution de code à distance de formiNICWpsStart
  • Vulnérabilité d'exécution de code à distance de formUSBStorage

Ainsi, après avoir chargé la version corrigée de webs dans IDA, nous avons cherché formHwSet dans la liste des fonctions et n'avons rien trouvé. En fait, beaucoup de ces fonctions n'ont pas été trouvées. En consultant Bindiff, nous pouvons voir que 7 fonctions ont été supprimées lors de la mise à jour :

capture d'écran de la liste des fonctions

Ces données correspondent bien à celles du bulletin de la ZDI. En fait, toutes les fonctions énumérées dans les avis de ZDI ont été supprimées, à l'exception de formWlanSetupWPS et formBSSetSitesurvey. Prenons le temps d'examiner les fonctions supprimées.

formUsbStorage

La première fonction que nous examinons est formUsbStorage. Après une lecture rapide de la fonction, le problème est assez évident. La variable POST sub_dir, à laquelle on accède via la fonction websGetVar de l'API GoAhead, est utilisée dans un appel au système, ce qui permet l'injection de commandes.

Capture d'écran de formUsbStorage

Ce code peut être déclenché via :

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

formWlanMP

Une erreur similaire peut être trouvée dans le formulaire actionformWlanMP. En retraçant les appels à websGetVar, nous voyons quelques possibilités.

Capture d'écran d'une erreur trouvée dans l'actionformWlanMP

Si l'on suit l'exemple, on voit que ces quelques possibilités peuvent toutes être injectées dans l'appel système -- nous avons choisi ateFunc.

Capture d'écran d'une erreur trouvée dans ateFunc

Ce code peut être déclenché via :

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

formHwSet

Il y a encore une injection de commande ici, cette fois nous utilisons la variable [sic] Anntena.

Capture d'écran de l'injection de la variable anntena dans la commande

Ce code peut être déclenché via :

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

formConnectionSetting

Ici, nous avons une injection de commande dans le paramètre timeOut de la fonction formConnectionSetting.

capture d'écran de l'injection de commande dans le paramètre timeOut de la fonction formConnectionSetting

Ce code peut être déclenché via :

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

formBSSetSitesurvey

À ce stade, nous avons fait le tour de la question des fonctions supprimées. Examinons la plus importante des fonctions que Belkin a décidé de ne pas supprimer : formBSSetSitesurvey. En voici un aperçu :

formBSSetSitesurvey overview

Après avoir reculé d'horreur, nous pouvons zoomer et voir que le changement majeur est que Belkin a ajouté une fonction appelée strcat_escape qui est utilisée tout au long de cette fonction sur les sources provenant de websGetVar.

Belkin a ajouté une fonction appelée strcat_escape

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"\\\"'$()<>` #&*

Nous avons réimplémenté cette fonction en C à partir du binaire webs et nous pouvons voir la sortie attendue :

sortie d'une fonction dans webs binary

Cette chaîne échappée (vraisemblablement correctement) est ensuite transmise normalement au système via sprintf, comme précédemment.

capture d'écran fonction sprintf

L'efficacité de ce patch dépend de plusieurs facteurs :

  • La fonction strcat_escape fonctionne complètement comme prévu
  • strcat_escape ne provoque pas involontairement des débordements de tampon ;-)
  • strcat_escape est utilisé pour toutes les entrées utilisateur qui aboutissent au système
  • Nous avons pris contact avec Belkin au sujet de certains de ces points.

Conclusion

Nous savons tous que la maturité de la sécurité du code des appareils embarqués est un problème. Ici, nous voyons que même dans les appareils sortis en 2014, cela reste un problème.