IMA5 2019/2020 P20 : Différence entre versions
(→Reverse engineering sur l'application mobile associée à l'objet) |
(→Ecoute de la communication application mobile - objet connecté) |
||
Ligne 149 : | Ligne 149 : | ||
===Ecoute de la communication application mobile - objet connecté=== | ===Ecoute de la communication application mobile - objet connecté=== | ||
− | + | La dernière piste pour récupérer le firmware de l'objet est l'écoute de la communication bluetooth ayant lieue entre l'objet connecté et l'application mobile pour le transfert de données ou de mise à jour. Ayant commencé à explorer cette piste en tout fin de projet, j'ai du faire avec le matériel disponible, un LimeSDR qui est un radio logiciel. La recherche d'un programme compatible avec le LimeSDR permettant de capturer les communications bluetooth n'a pas été très fructueuse puisque je n'ai trouvé qu'un seul outil sous forme de projet sur github, [https://github.com/jocover/BLESDR blesdr]. Après 3 tentatives, ce programme ne m'a permis de récupérer que les paquets d'advertising. | |
− | + | Après quelques recherches il semblerait qu'un development kit nRF52 ou 51 ou un Adafruit Bluefruit programmés avec le nRF sniffer permettraient de réaliser l'action souhaitée et de manière beaucoup plus simple. | |
==Reverse engineering sur l'application mobile associée à l'objet== | ==Reverse engineering sur l'application mobile associée à l'objet== |
Version du 17 décembre 2019 à 18:40
Sommaire
- 1 Présentation générale
- 2 Préparation du projet
- 3 Réalisation du Projet
- 4 Documents Rendus
Présentation générale
Description
Les objets connectés commencent à se démocratiser dans les habitations (thermostats connectés, caméras connectés, serrures connectées, ...) et dans l'industrie (remontée de données, supervision, ...). Le marché de l'IOT (Internet Of Things) est très concurrentiel et les produits doivent être mis sur le marché rapidement à bas coût. Les problématiques de sécurités sont donc très souvent délaissées. De plus, les faibles performances et les tailles de mémoires limitées empêchent d’implémenter les méthodes classiques du monde Internet (anti-virus, pare-feux, mise à jour, certificats ,...).
Ce projet propose de concevoir et réaliser les briques de base d'une plateforme d'évaluation de la sécurité d'objets connectés :
- Une partie logicielle permettant la récupération de code embarqué, la décompilation, la compilation, ...
- Une partie matérielle permettant d'accéder aux données d'un objet (récupération du firmware) et l'injection de signaux ;
- Une éventuelle base de données permettant de sauvegarder les résultats et les failles trouvées.
Objectifs
Dans un premier temps, l'objectif sera d'être capable de récupérer les données utilisateur d'un objet connecté puis son firmware dans le but d'y trouver de potentielles failles de sécurité. Le code source de l'application mobile associée à l'objet pouvant lui aussi être source de failles de sécurité, sera de même à analyser.
Dans un second temps, le but ultime de ce projet serait d'automatiser une partie de ce processus et de le rendre utilisable pour un grand nombre d'objets connectés divers et variés.
Préparation du projet
Cahier des charges
Choix techniques : matériel et logiciel
Pour la partie matérielle, ce projet nécessite :
- Un objet connecté à exploiter à définir avec les encadrants, dont le nom et les résultats obtenus sur ce dernier ne seront pas explicités ici
- Convertisseur USB - TTL pour l'exploitation de pins de communication série
- Segger JLink pour l'exploitation de pins de Serial Wire Debug
Pour la partie logicielle, de nombreux outils pourraient être utiles à ce projet et seront à investiguer :
- Ghidra
- Radare2
- Binwalk
- Firmwalker
- Apktool
- dex2jar
- JDGUI
- CFR decompiler
- OWASP ZAP
- Android Debug Bridge
- Android backup extractor
Liste des tâches à effectuer
Ce projet se découpe en 4 tâches principales :
- Récupération des données utilisateur de l'objet
- Récupération du firmware de l'objet et analyse dans le but de trouver des failles de sécurité
- Analyse du code source de l'application mobile associée à l'objet dans le but de trouver des failles de sécurité
- Automatisation d'une partie des trois premières tâches
Calendrier prévisionnel
Réalisation du Projet
Récupération du code d'une carte Arduino Uno
Afin de pouvoir me familiariser avec le sujet, les différents logiciels disponibles et en attendant d'avoir l'objet sur lequel travailler, j'ai utilisé une carte Arduino Uno. Après y avoir téléversé un des programmes proposés en exemple sur l'IDE Arduino qui allume puis éteint la LED chaque seconde, j'ai tenté de le récupérer via le port série. Pour cela j'ai utilisé l'utilitaire avrdude qui permet de réaliser des actions sur la mémoire d'un microcontroleur AVR comme présent sur l'arduino.
J'ai alors pu extraire de la mémoire flash de l’Arduino un fichier Intel Hex avec la commande suivante :
avrdude -c arduino -P /dev/ttyACM0 -p m328p -b 115200 -U flash:r:blink.hex:i
Une fois en possession de ce fichier, j'ai utilisé l'outil Ghidra, outil de reverse engineering développé par la NSA, afin de pouvoir analyser le contenu du fichier dans une forme plus compréhensible :
L’outil nous permet alors, de visualiser le contenu du fichier sous forme de code assembleur mais aussi sa transposition en code C.
Sur la partie gauche, l’outil nous présente toutes les fonctions qu’il a pu reconstruire à partir du fichier. Il est cependant impossible de retrouver les noms de fonctions ou variables personnalisées utilisées dans le code qui a été téléversé sur l’Arduino. Les fonctions sont alors nommées FUN_code_xxxxxx. Le code C obtenu est très bas niveau avec de la manipulation d’adresses mémoire, de registres etc. Sachant ici à quoi le code d’origine ressemble, on retrouve très vite que le void loop() du programme d’origine correspond ici au do { … } while (true) de la fonction FUN_code_000160 que l’on peut voir sur la capture d’écran ci-dessus. La fonction FUN_code_000070 correspond à la fonction digitalWrite() du programme d’origine et la fonction FUN_code_0000de correspond à la fonction delay.
Etant donné que Ghidra n’est pas capable de retrouver les librairies C utilisées à partir du fichier Intel Hex donné (contrairement à lorsqu’on lui donne un fichier ELF), il devient très vite compliqué de s’y retrouver lorsque le code d’origine utilise de nombreuses fonctions importées.
J’ai aussi pu tester le framework Radare2 qui a la même finalité que Ghidra. Il s’avère plus compliqué à prendre en main et moins ergonomique. Lors de l’analyse du fichier obtenu précédemment, Radare2 donne en résultat qu’une unique fonction en langage assembleur et ne permet pas de la transposer en code C. L’utilisation de Ghidra sera donc très certainement préférée pour ce projet.
Récupération de données utilisateur et firmware d'un objet connecté
Exploitation des pins présent sur le circuit
En ouvrant l'objet connecté étudié, nous nous sommes rendus compte de la présence de pins de debug RX, TX, CLK, IO, VCC, GND. Avec l'aide de Thierry Flamen, nous avons soudé des fils de connexion sur chacun de ces pins afin de pouvoir les exploiter.
Dans un premier temps, j'ai utilisé un convertisseur série -> USB afin d'exploiter les pins TX et RX. Je n'ai eu aucun résultat avec minicom. Afin de vérifier que rien n'était envoyé par l'objet sur les Rx et Tx, j'ai utilisé un oscilloscope. La différence de potentielle observée entre les pins Tx et GND était trop faible pour qu'une quelconque information ne soit envoyée via l'UART de l'objet.
Dans un second temps, j'ai utilisé un JLink SEGGER debugger, dispositif permettant de debugger des micro-controleurs dont celui présent dans l'objet étudié. Le constructeur du micro-controleur en question met à disposition un outil en ligne de commande permettant entre autres de programmer la puce ou de lire son contenu par l'intermédiaire du JLink. J'ai alors connecté ce dernier à l'objet avec les pins de Serial Wire Debug CLK et IO présents sur le circuit puis tenté de récupérer le firmware :
J'ai alors été confronté à une protection empêchant la lecture des données. Après quelques recherches, le seul moyen d'enlever cette protection serait d'effacer le contenu du micro-contrôleur et de le reprogrammer. Cela n'est pas envisageable puisque ceux sont les données actuellement présentes dans l'objet que je souhaite récupérer.
Ecoute de la communication entre l'application mobile étudiée et le serveur distant
Suite à ces deux impasses, j'ai du me tourner vers la dernière piste pour la récupération des données de l'objet, à savoir, exploiter le fait que l'objet puisse être mis à jour à partir de l'application mobile associée.
Afin de mettre à jour l'objet connecté, après appairage, l'application mobile réalise des appels API sur un serveur distant afin de vérifier si l'objet est à jour ou non et récupérer la dernière version du firmware. J'ai donc décidé d'observer ces communications afin de voir si il y avait quelque chose à exploiter à ce niveau. Pour cela, j'ai utilisé le logiciel OWASP ZAP qui est un proxy présentant de nombreuses fonctionnalités de pentest. Après avoir installé ce proxy sur mon ordinateur. J'ai configuré un smartphone android pour utiliser ce dernier. Dès lors, toutes les requêtes HTTP passent par l'OWASP ZAP avant d'atteindre leur cible. Le logiciel permet alors de visualiser toutes les requêtes réalisées à partir du smartphone avec les différents paramètres envoyées ainsi que les réponses reçues. Une fois le proxy mis en place, j'ai pu visualiser les différents échanges réalisées entre l'application mobile associée à l'objet connecté à son lancement et le serveur distant. Un premier appel de login est réalisé au lancement de l'application. J'ai pu retrouver en clair sur le logiciel servant de proxy, les paramètres associées à cet appel, à savoir, mon adresse email servant de login ainsi que mon mot de passe. Les identifiants étant corrects, le serveur distant envoie en réponse un token nécessaire à tous les autres appels API. Ce token est aussi lisible sur le logiciel. Après avoir récupéré mon token, j'ai tenté de réaliser un appel API via Postman. Cela a fonctionné et nous pouvons donc de cette façon, récupérer les données stockées sur le serveur distant.
Après ce premier appel de login, un appel de vérification de la version du firmware est réalisé. L'objet en ma possession n'étant pas à jour, il s'en est suivi un autre appel afin de récupérer la mise à jour à appliquer sur l'objet. La mise à jour a alors été téléchargé sur le smartphone. Après avoir installé un explorateur de fichiers sur ce dernier, j'ai rapidement retrouvé le fichier de mise à jour téléchargé. Malheureusement, ce fichier d'extension .des semble être un fichier encrypté. Une mesure de l'entropie du fichier sur binvis.io me l'a confirmé. 'des' étant l'acronyme pour Data Encryption Standard, une méthode ancienne de cryptage de données, j'ai cherché un moyen de décrypter le fichier par bruteforce. Je n'ai malheureusement trouvé aucun programme permettant cela.
Analyse d'un firmware
N'ayant pas pu exploiter le fichier récupéré de l'API Terraillon, j'ai utilisé le "Damn Vulnerable Router Firmware" qui est un firmware dédié à l'expérimentation afin de tester les différents logiciels existants pour l'analyse d'un firmware.
Après avoir récupéré le binaire du firmware, j'ai utilisé Binwalk. Binwalk est un outil d'analyse de firmware qui permet de scanner la signature d'un binaire, d'analyser les différents fichiers y étant présents, d'en réaliser une extraction ou encore de mesurer l'entropie du binaire afin de savoir si le firmware est encrypté ou non.
Nous pouvons voir ici que l'analyse avec Binwalk pour le firmware étudié a détecté un système de fichier squashfs ainsi qu'une partie de données compressées nommée "piggy".
On peut alors procéder à l'extraction avec la commande :
binwalk -e binaireàExtraire.bin
L’exécution de la commande précédente fait apparaître un dossier contenant le fichier de données "piggy" ainsi que le système de fichier du firmware extrait :
Le travail de rétro ingénierie peut ensuite commencer dans le but de trouver de potentielles failles de sécurité. Pour cela, il existe Firmwalker qui est un outil qui va mettre en valeur certains fichiers, scripts ou chaînes de caractères trouvés dans le système de fichier extrait du firmware qui sont susceptibles de compromettre la sécurité de l'objet dans lequel est installé le firmware :
L'outil parcourt le système de fichier pour y trouver tout ce qui est relatif à :
- fichiers etc/shadow et etc/passwd
- répertoire etc/ssl
- fichiers relatifs au protocole SSL
- fichiers de configuration
- scripts
- fichiers d'extension .bin
- mots clés comme "admin", "password", etc
- présence de serveur web courants dans l'IoT
- présence de binaires courants comme ssh, tftp, telnet, etc
- URLs, adresses mail et adresses IP
Le résultat est sauvegardé dans un fichier .txt.
Cet outil permet un gain de temps conséquent et est semblable à ce que nous avions prévu de réaliser dans la partie automatisation pour l'analyse du code source d'applications mobiles.
Ecoute de la communication application mobile - objet connecté
La dernière piste pour récupérer le firmware de l'objet est l'écoute de la communication bluetooth ayant lieue entre l'objet connecté et l'application mobile pour le transfert de données ou de mise à jour. Ayant commencé à explorer cette piste en tout fin de projet, j'ai du faire avec le matériel disponible, un LimeSDR qui est un radio logiciel. La recherche d'un programme compatible avec le LimeSDR permettant de capturer les communications bluetooth n'a pas été très fructueuse puisque je n'ai trouvé qu'un seul outil sous forme de projet sur github, blesdr. Après 3 tentatives, ce programme ne m'a permis de récupérer que les paquets d'advertising. Après quelques recherches il semblerait qu'un development kit nRF52 ou 51 ou un Adafruit Bluefruit programmés avec le nRF sniffer permettraient de réaliser l'action souhaitée et de manière beaucoup plus simple.
Reverse engineering sur l'application mobile associée à l'objet
Les objets connectés ne pouvant pas embarquer une grande quantité de mémoire du fait de leur petite taille, les données mesurées sont la plupart du temps envoyés et stockés sur un serveur distant. Généralement, il est alors proposé une application mobile associée à l'objet permettant de synchroniser les nouvelles données mesurées et les visualiser.
C'est le cas pour l'objet connecté étudié qui est proposé avec une application mobile associée. Cette application permet d'analyser les données récupérées par l'objet après synchronisation. Pour cela, l'application doit interagir avec l'objet mais aussi le serveur distant sur lequel vont être stockées les données. Le code de l'application peut donc potentiellement contenir des informations pouvant compromettre la solution.
Décompilation
Après avoir téléchargé le fichier APK de l'application, j'ai utilisé différents outils pour décompiler le code afin de pouvoir l'analyser.
Dans un premier temps, j'ai utilisé l'outil dex2jar afin de convertir le fichier APK en un JAR :
d2j-dex2jar.sh application.apk
J'ai ensuite utilisé JD-GUI pour décompiler le JAR et visualiser le code source. Il m'a fallu ajouter des droits d’exécution et de lecture sur le JAR afin d'éviter une erreur peu explicite lors de l'import du JAR sur l'outil. Le code récupéré n'étant pas offusqué, j'ai pu l'analyser.
Analyse du code source
Je suis assez vite tombé sur un fichier de constantes contenant l'adresse de l'API du constructeur ainsi que ses différents endpoints utilisées afin d'agir sur les données utilisateurs. Cette API permet par exemple de récupérer les informations de profil utilisateur, de les éditer, de récupérer les données mesurées par le capteur de différentes façons ou encore de télécharger des mises à jour de firmware.
L'application utilise une base de données fichier SQLite stockée sur le téléphone de l'utilisateur composée d'une table regroupant les différentes mesures pouvant être prises avec l'objet associé mais aussi avec deux autres, l'application étant commune à trois différents proposés par le constructeur.
Après avoir découvert cela, j'ai creusé un peu plus afin de savoir comment était synchronisé l'ensemble des données entre l'objet, la base de données sur le téléphone ainsi que l'API.
A son inscription, l'utilisateur fournit des données sur lui même l'identifiant et aidant à analyser les données récupérées par l'objet. Ces données utilisateur sont envoyées directement sur le serveur distant grâce à un certain endpoint de l'API. L'utilisateur peut alors ensuite se connecter sur l'application avec le login et le mot de passe entrés lors de son inscription. La vérification de son identité est faite par un appel API qui, si l'utilisateur est reconnu par le serveur, fournit un token qui permettra d'identifier l'utilisateur pour les appels API concernant les actions sur les données récupérées par l'objet.
Une fois connecté, l'utilisateur peut appairer son objet à l'application via bluetooth puis synchroniser les données mesurées par l'objet. Toutes les données présentes sur l'objet sont alors récupérées sur l'application via le bluetooth et celles qui ne sont pas présentes en base de données (la vérification est faite en comparant la date des mesures) sont stockées en base de données sur le téléphone avec un certain champ indiquant que ces données n'ont pas encore été téléchargé sur l'API. Si le téléphone mobile est connecté à internet, toutes les données de la base dont le champ en question est dans l'état "non téléchargé" sont envoyées sur le serveur distant à travers l'API grâce au token d'identification de l'utilisateur récupéré à sa connexion. L'état des données uploadées est alors modifié pour ne pas qu'elles soient envoyées une deuxième fois sur le serveur distant.
Lorsque l'utilisateur consulte la page d'analyse des données sur son application, les données à analyser sont récupérées dans la base de données si présentes sinon, sur le serveur distant par appel API. Elles peuvent être récupérées sur différentes périodes selon la page consultée sur l'application. Lorsque les données sont récupérées pour les trente derniers jours, les données de la base sur le téléphone sont effacées et remplacées par les données récupérées grâce à l'API. La base de données ne sert donc qu'à stocker temporairement les données afin de pouvoir répondre aux demandes de l'utilisateur dans le cas ou son téléphone n'est pas connecté à internet. Elle joue aussi un rôle de cache.
J'ai aussi pu me rendre compte que lorsque l'on quitte l'application en y étant connecté, on l'est toujours en relançant l'application. Le login et le mot de passe doivent donc être stockés quelque part. L'analyse du code m'a permis de découvrir que ces données sensibles sont bien stockées sur le téléphone grâce au système de préférences d'application Android. Les données sont stockées en clair au format clé-valeur dans un fichier qui n'est supposé être accessible que par l'application.
En dehors de cet aspect stockage de données, j'ai pu voir dans le code qu'il y avait une fonctionnalité de mise à jour du firmware de l'objet connecté via l'application avec notamment de nombreuses mentions à la norme de transmission OTA, "over the air". Cela constitue une piste pour la partie récupération de firmware de l'objet connecté.
Exploitation
En analysant le manifeste android de l'application, j'ai pu localiser la présence d'une propriété très interessante :
android:allowBackup="true"
Cette propriété, mise à "true" par défaut, permet de réaliser une récupération des données de l'application via les outils Android. J'ai donc tenté de récupérer les différentes informations que stocke l'application étudiée dans le téléphone. Pour cela j'ai utilisé l'outil Android Debug Bridge, un outil android en ligne de commande qui permet de réaliser différentes opérations sur un téléphone android. Après avoir activé le mode développeur sur le smartphone utilisé, étape nécessaire pour réaliser la récupération, je l'ai connecté à mon ordinateur. La commande
adb devices -l
permet lister les périphériques détectés. Mon smartphone étant bien reconnu, j'ai cherché le nom du package android lié à l'application étudiée afin de ne lancer la récupération que pour cette application. Pour cela, la commande
adb shell pm list packages
permet de lister tous les packages présents dans le téléphone. Une fois en possession du nom de package désiré, j'ai pu lancé la récupération des données avec la commande :
adb backup -f {nom_du_fichier_backup} {nom_du_package_cible}
Après avoir accepté l'opération de récupération sur le smartphone en précisant ou non un mot de passe pour encrypter les données, un fichier d'extension .ab apparaît à l'emplacement spécifié. Afin de pouvoir exploiter les données contenues dans ce fichier, j'ai utilisé l'outil Android backup extractor permettant de convertir un fichier android backup en une archive compressée :
java -jar abe.jar unpack {fichier_a_convertir.ab} {nom_de_l'archive.tar} {mot_de_passe}
J'ai enfin pu décompresser l'archive obtenue avec la commande précédente et visualiser les données de l'application. J'ai pu y trouver le fichier utilisé par le mécanisme de SharedPreferences Android que j'avais localisé dans le code contenant entre autres mon login ou encore mon mot de passe en clair. J'ai aussi pu y trouver le fichier de base de données utilisé par l'application avec les données enregistrées.
Au cours de l'analyse du code source, j'ai pu remarquer que certaines informations étaient loggées. Android Debug Bridge m'a alors été encore utile puisqu'il m'a permis de suivre les logs de l'application avec logcat via la commande :
adb logcat {nom_package_cible}
Malheureusement je n'ai pas pu tirer d'informations importantes des logs de l'application.