
MikroTik remote jailbreak for v6.x.x
______ ____ _____ _____ _ _
| ____/ __ \_ _|/ ____| | | |
| |__ | | | || | | (___ | |_ ___ __| |
| __|| | | || | \___ \| __/ _ \/ _` |
| | | |__| || |_ ____) | || __/ (_| |
|_| \____/_____|_____/ \__\___|\__,_|
FOISted est un exploit pour deux vulnérabilités post-authentification dans le RouterOS de MikroTik. Il peut être utilisé pour jailbreaker à distance RouterOS, de 6.34 (2016) à 6.49.6 (dernière version de la série v6).
Ce dépôt comprend un script d'exploit pour les appareils fonctionnant sous x86. La vulnérabilité existe également sur d'autres versions d'appareils ; l'écriture de la ropchain est laissée en exercice au lecteur :)
Pour plus d'informations, consultez notre article de blog sur les rouages internes de RouterOS : https://margin.re/blog/pulling-mikrotik-into-the-limelight.aspx
Automatique :
$ python3 exploit.py -H <router_ip> -u <username> -p <password>
Ensuite :
$ nc <router_ip> 1337
Le script d'exploit déterminera la version de RouterOS et déploiera automatiquement la ropchain appropriée. Remarque : actuellement, seul RouterOS x86 est pris en charge.
Si votre version n'est pas identifiée pour une raison quelconque, vous pouvez la passer explicitement avec :
-v <version> # e.g. 6.49.6
Si vous exécutez ceci sur des versions de RouterOS plus récentes que 6.49.6 (la plus récente au moment de la publication publique), votre version de RouterOS pourrait ne pas figurer dans la base de données de gadgets (./db). Vous pouvez alors passer le chemin vers /nova/bin/www et le script d'exploit essaiera automatiquement de trouver les gadgets appropriés pour la ropchain :
-f /path/to/nova/bin/www
FOISted exploite deux vulnérabilités dans RouterOS v6 pour permettre l'exécution de code à distance. Dans cette section, nous passons en revue quelques connaissances de base sur l'IPC de RouterOS et discutons des deux vulnérabilités.
Remarque : cette section est en grande partie une version abrégée de notre article de blog complet. N'hésitez pas à le consulter pour plus de détails !
Dans le RouterOS de MikroTik, les programmes communiquent entre eux à l'aide d'un protocole IPC personnalisé.
Les véritables paquets de données sont des Nova Messages (nv::message en interne). Ils existent dans un format pseudo-JSON (avant la 6.38) et un format binaire sérialisé :

Chaque processus a une adresse fixe dans le système RouterOS ; par exemple, /nova/bin/user est à l'adresse 13 et /nova/bin/www à l'adresse 70. De plus, chaque programme peut enregistrer des handlers qui implémentent certaines fonctionnalités spécifiques dans un sous-espace de noms. Par exemple, /nova/bin/user a un handler à l'adresse 4 qui agit comme point de terminaison « login » et effectue l'authentification pour d'autres services :

La communication IPC est un élément crucial du fonctionnement de RouterOS. Elle est utilisée pour :
Au cours de nos efforts de rétro-ingénierie, nous avons écrit un outil interne de trace de messages qui nous permet de visualiser tous les messages échangés pendant le fonctionnement du routeur.
Dans la démo suivante, vous pouvez voir tous les messages échangés lorsque nous naviguons dans l'interface web : https://youtu.be/Em1hVWnbzQ4
L'interface web de RouterOS est implémentée par le binaire /nova/bin/www. Cependant, certaines pages peuvent être prises en charge par des bibliothèques « Servlet » distinctes qui implémentent des fonctionnalités dans des bibliothèques partagées séparées.
Par exemple, le servlet jsproxy.p gère les requêtes vers /jsproxy et le servlet winbox.p gère les requêtes vers /winbox, etc...
Ces servlets sont des bibliothèques qui sont chargées dans /nova/bin/www la première fois qu'elles sont nécessaires. Par exemple, la première fois que nous chargeons /jsproxy, la bibliothèque jsproxy.p sera chargée dans l'espace mémoire.
Au cours de ce processus de chargement de bibliothèque, nous avons remarqué un trafic intéressant dans le traceur de messages :

Plus précisément, nous avons trouvé un message qui était envoyé depuis le binaire www vers le handler #2 de www. C'est déjà suspect car l'IPC de RouterOS est destiné à la communication inter-processus et non à une communication à l'intérieur du même processus...
De plus, nous avons remarqué que deux des arguments semblaient être des pointeurs virtuels (x86 32 bits), ce qui a éveillé notre intérêt car c'était très inhabituel.
En inspectant les fonctions réelles du handler #2 de /nova/bin/www, nous trouvons une fonction appelée FoisHandler::cmdUnknown qui est exécutée lorsque ces types de messages sont reçus.
Étonnamment, cette fonction extrait le paramètre 0x11 du message et l'invoque comme une fonction en utilisant deux des autres paramètres comme arguments !
Clairement, si nous pouvons envoyer un message contrôlé qui atteint ce handler, nous pouvons invoquer n'importe quelle fonction que nous voulons. Et de là, il est assez facile de pivoter vers une ropchain et de faire quelque chose de plus sophistiqué.
En tant qu'utilisateur de RouterOS, il existe plusieurs moyens d'envoyer des messages IPC internes. En fait, tous les clients externes permettent d'envoyer des messages arbitraires après authentification :
8291) -- utilisé par le client winbox.exeCes interfaces diffèrent dans la manière dont elles effectuent la poignée de main d'authentification initiale, mais une fois authentifié, elles permettent à un utilisateur de relayer des Nova Messages arbitraires vers le système interne. Consultez notre article de blog et notre dépôt pour la rétro-ingénierie des protocoles cryptographiques Winbox et MAC Telnet !
Dans cette implémentation de l'exploit, nous utilisons le point de terminaison WebFig comme principal mécanisme de communication. Voir webfig.py pour notre implémentation de client issue de la rétro-ingénierie.
Cependant, il y a un problème lorsque nous essayons d'invoquer notre point de terminaison vulnérable FoisHandler :
Chaque handler dans RouterOS peut définir un masque de bits « policy » qui spécifie quels utilisateurs sont autorisés à l'invoquer. Il s'avère que FoisHandler a une politique de 0x80000000 qui n'indique qu'un accès interne (c'est-à-dire les messages provenant d'autres processus système).
En tant qu'utilisateur admin, le masque de bits de permission maximal que nous pouvons définir avec l'interface graphique n'est que 0x7fffe, ce qui n'est pas suffisant.
Ceci nous amène à notre deuxième bug : une élévation de privilèges d'admin à « super-admin ».
Alors que l'interface graphique ne nous permet de définir qu'un masque de bits de permission de 0x7fffe, en interne elle envoie en réalité simplement un message IPC avec l'un des champs contenant la valeur du masque de bits :

Nous pouvons donc simplement forger notre propre message avec la valeur du masque de bits de permission définie sur 0xffffffff !
Une fois cela fait, nous avons désormais un accès illimité pour atteindre n'importe quel point de terminaison du système !
Notre exploit commence par téléverser deux fichiers vers le système via FTP :
stage2 : contenant un générateur de shell inversé qui écoute sur le port 1337busybox : nous fournissant un environnement shell adéquatNotre exploit effectue ensuite une élévation de privilèges pour nous permettre d'atteindre le point de terminaison FoisHandler.
Enfin, nous envoyons un message forgé pour pivoter vers une ropchain intégrée dans le message. La ropchain calcule l'adresse de chmod et execve dans uClibc et effectue :
chmod 0777 stage2execve stage2Une fois stage2 en cours d'exécution, vous pouvez vous connecter au port 1337 et obtenir un shell !
Non, ces deux vulnérabilités nécessitent des identifiants admin pour être exploitées.
Les vulnérabilités existent depuis au moins 6.27 (le plus ancien logiciel que nous ayons pu télécharger) jusqu'à la version v6 la plus récente : 6.49.6. L'interface web a été refactorisée dans RouterOS v7 et le handler vulnérable a été entièrement supprimé. Notre POC est écrit pour x86.
Le script d'exploit fonctionne (testé !) sur toutes les versions de RouterOS de 6.34 à 6.49.6.