
Exploit pour le modem câble Sagemcom F@ST 3890 exploitant la vulnérabilité Cable Haunt pour obtenir une exécution de code à distance via un débordement de tampon basé sur WebSocket et une chaîne ROP.
Cet exploit utilise la vulnérabilité Cable Haunt pour ouvrir un shell sur le modem câble Sagemcom F@ST 3890 (50.10.19*), à partir d'un accès au réseau local. La version du firmware 50.10.21 ou plus récente devrait être sécurisée contre Cable Haunt. Cette preuve de concept a spécifiquement été conçue pour ne fonctionner que localement afin de limiter le potentiel d'utilisation malveillante. Une autre POC qui crée un reverse shell vers une connexion externe pour le Technicolor TC7230 est disponible ici.
Une liste des modems vulnérables connus peut être trouvée sur https://cablehaunt.com/#faq-am-i-affected.
Le script exploit.py sert un site web qui, lorsqu'il est visité, envoie une requête WebSocket malveillante au modem câble.
Cette requête provoque un débordement de l'adresse de retour et des registres associés dans l'analyseur de spectre (Spectrum Analyzer) du modem câble, et utilise une chaîne ROP pour commencer à écouter une connexion TCP sur le port 1337.
La chaîne ROP est construite et commentée dans static/exploitSagemcom.js.
Le serveur exploit.py envoie ensuite le fichier exploit.raw via cette connexion TCP, fichier qui sera ensuite exécuté par le modem.
Le fichier exploit.raw provient de reverseshell.c compilé pour l'architecture MIPS (voir la méthode ci-dessous).
Reverseshell.c est un shell écrit explicitement pour ce modem. Le shell écoute les commandes à exécuter dans le shell eCos du modem câble et redirige STDOUT vers la connexion TCP.
Vous pouvez trouver une vidéo expliquant l'exploit ici : https://www.youtube.com/watch?v=5FM9mS5ck3Y
Remarque : Windows 10 n'est actuellement pas pris en charge, vous devez utiliser un OS basé sur Linux
Installez pwntools et flask pour python3 puis exécutez python exploit.py.
Rendez-vous ensuite sur http://127.0.0.1:8080 dans votre navigateur pour exploiter le modem.
Firefox ne fonctionnera pas ici, car la version de WebSocket utilisée n'est pas compatible.
Un shell interactif devrait alors apparaître dans votre terminal exécutant le script python. Si vous quittez le shell, le modem doit être redémarré pour démarrer un nouveau shell.
Si vous souhaitez compiler votre propre payload, vous pouvez récupérer la toolchain depuis aeolus et exécuter la commande suivante :
/<toolchain Path>/gnutools/mipsisa32-elf/bin/mipsisa32-elf-gcc -O3 -c ./reverseshell.c -o ./reverseshell.o && /<toolchain Path>/toolchains/gnutools/mipsisa32-elf/bin/mipsisa32-elf-objcopy -O binary reverseshell.o exploit.raw
Vous pouvez construire et exploiter n'importe quel modem vulnérable à Cable Haunt en utilisant cette technique. Nous recommandons de lire le rapport technique avant d'essayer d'écrire votre propre chaîne ROP. Rendez-vous sur Cable Haunt pour obtenir une liste des modems câble vulnérables connus.
Tout d'abord, vous aurez besoin du firmware du modem câble que vous allez exploiter. Ensuite, faites de la rétro-ingénierie du firmware pour trouver les adresses des fonctions pertinentes pour la construction de l'exploit, telles que socket(), bind(), accept(), listen(), recv() et connect() pour un shell. Ensuite, Ropper peut être utilisé pour trouver des gadgets à l'aide de la commande suivante :
python Ropper.py --type all --all --badbytes 00c0c1f5f6f7f8f9fafbfcfdfeff2c -r -a MIPSBE -I 0x80004000 --console -f <firmware path>
Tous les gadgets ne sont pas accessibles, car les gadgets ne sont que des adresses envoyées sous forme d'octets bruts et tous les octets ne peuvent pas être envoyés dans une requête WebSocket avec des trames texte.
Par exemple, l'adresse 0x8080a864 ne peut pas être insérée directement dans une trame texte WebSocket, car ce n'est pas un caractère UTF-8 valide. L'adresse 0xf28080a864 peut en revanche être insérée, car 0xf2 signifie qu'un nouveau symbole UTF-8 commence avec 0x8080a864 comme octets de fin.
Les octets suivants ne peuvent être présents dans aucune adresse utilisée en raison de la spécification UTF-8 : 0x00, 0xc0,0xc1,0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x2c. Il existe également d'autres restrictions qui seront bientôt expliquées plus en détail dans notre rapport.
Pour l'instant, vous pouvez lire et utiliser utf8TestScript.py pour tester si une adresse est accessible.
Vous pouvez utiliser le processus décrit ci-dessus pour compiler votre propre payload pour un nouveau modem câble, mais rappelez-vous que le payload ne doit pas retourner ! S'il retourne, le processus cherchera une adresse de retour sur la pile écrasée et plantera.
Pour la plupart des modems, vous aurez besoin d'un moyen d'accéder au shell eCos pour extraire le firmware ou de l'extraire directement de la puce flash. Ces firmwares sont généralement conditionnés dans un format appelé ProgramStore Si la console série ne fonctionne pas, essayez d'exécuter : (cela peut ne fonctionner que si le câble coaxial est déconnecté ou non provisionné)
snmpset -v2c -c private 192.168.0.1 1.3.6.1.4.1.4413.2.2.2.1.9.1.2.1.0 i 2
snmpset -v2c -c private 192.168.0.1 1.3.6.1.4.1.4413.2.2.2.1.9.1.2.1.0 i 0
snmpset -v2c -c private 192.168.0.1 1.3.6.1.4.1.4413.2.2.2.1.9.1.2.1.0 i 2
Le shell devrait alors être accessible, et bcm2-utils peut faciliter son extraction à l'aide de ce shell. Lors de la rétro-ingénierie du firmware extrait, l'adresse de chargement/de base est (d'après ce que nous avons vu) toujours 0x80004000.