Les applications mobiles sont de plus en plus utilisées dans tous les domaines d’activités : RH, finance, assurances, transports, etc. De fait, elles constituent des cibles de choix pour les attaquants.
Il existe plusieurs moyens d’évaluer la sécurité d’une application mobile. Dans cet article, nous vous présentons l’approche « offensive » qui reste, selon nous, la plus efficace : les tests d’intrusion mobile (ou pentest mobile). Nous y détaillons les principes, objectifs ainsi que la méthodologie et les éléments testés lors de tests d’intrusion d’application mobile.
Plan détaillé de l’article :
- En quoi consiste un test d’intrusion d’application mobile ?
- L’écosystème des applications mobiles
- Périmètre d’un test d’intrusion mobile
- Focus sur la norme MASVS (Mobile Application Security Verification Standard) de l’OWASP
- Stockage non sécurisé de données sensibles
- Divulgation d’informations sensibles via les logs
- La sécurité des communications réseau
- Les permissions de l’application
- Deep links sur Android
- Données sensibles dans le code de l’application
- Prise en charge d’anciennes versions iOS ou Android
- Focus sur la vulnérabilité Android Janus
En quoi consiste un test d’intrusion d’application mobile ?
Un test d’intrusion d’application mobile consiste à évaluer la sécurité d’une application mobile via une mise en situation reproduisant les conditions d’une attaque.
En général, il est rare de trouver une application mobile qui ne communique pas avec un ou plusieurs serveurs. Par conséquent, un test d’intrusion mobile inclut :
- Des tests côté serveur via une analyse des communications, la plupart du temps HTTP/HTTPS. Dans ce cas de figure, les tests dont identiques à un pentest web. Et c’est généralement sur ce pan que l’on trouve les vulnérabilités les plus critiques. Néanmoins, il peut arriver que l’application ne communique pas avec un serveur, ou utilise d’autres protocoles comme MQTT.
- Des tests spécifiques relatifs aux fonctionnalités propres de l’application mobile.
Ces différentes évaluations seront examinées en détail dans les sections suivantes de cet article.
Les résultats des tests sont consignés dans un rapport d’audit qui détaille la méthodologie employée, les vulnérabilités découvertes, leurs impacts, les scénarios d’exploitations possibles, ainsi que des recommandations pour les corriger.
L’écosystème des applications mobiles
Aujourd’hui, Android et iOS représentent 99% des systèmes d’exploitation. Nous ne parlerons donc ici que de ces deux acteurs majeurs.
Il existe ensuite plusieurs types d’application différents :
Les applications natives
Une application native est une application qui utilise les SDK (Software Development Kit) pour créer des applications spécifiques à l’OS. L’avantage des applications natives est leur performance, et la possibilité d’interagir avec la plupart des composants du téléphone (capteur, appareil photo, etc.). L’inconvénient notable est une divergence au niveau de la base de code, entraînant des différences significatives en fonction de la cible. Même le langage de programmation est différent, généralement Java ou Kotlin pour Android et Objective-C ou Swift pour iOS.
Cependant, il existe des frameworks permettant d’avoir une base commune. Par exemple nous pouvons citer Xamarin, Flutter et React Native. Malgré la base commune, l’application finale peut être considérée comme une application native avec le même degré de performance et l’accès au même composant qu’en utilisant directement les SDK.
Les applications hybrides
Les applications hybrides sont des applications qui s’exécutent principalement dans une WebView, c’est-à-dire un navigateur intégré. L’avantage des applications hybrides contrairement à une application purement web, c’est que celles-ci peuvent accéder à des fonctionnalités de l’appareil.
Tout comme les applications natives là encore, il existe plusieurs frameworks permettant la création de ces applications comme Cordova, Ionic.
Progressive Web App (PWA)
Ces applications se chargent comme des pages Web ordinaires, mais avec quelques différences avec des applications Web classiques comme la possibilité de travailler hors ligne et d’accéder à certaines fonctionnalités matérielles.
Périmètre d’un test d’intrusion mobile
Focus sur la norme MASVS (Mobile Application Security Verification Standard) de l’OWASP
MASVS est la norme en matière de sécurité des applications mobiles. Cela nous permet de garantir l’exhaustivité et la cohérence des résultats de tests.
L’OWASP classe les différents contrôles à effectuer sur des applications mobiles en 7 sections :
- MASVS-STORAGE : assurer un stockage sécurisé des données sensibles.
- MASVS-CRYPTO : mettre en place des fonctionnalités cryptographiques afin de protéger les données sensibles.
- MASVS-AUTH : mettre en œuvre des mécanismes d’authentification et d’autorisation au sein de l’application mobile.
- MASVS-NETWORK : garantir la sécurité des données en transit lors des communications.
- MASVS-PLATFORM : assurer la sécurité des interactions de l’application mobile avec les autres applications installées.
- MASVS-CODE : suivre les meilleures pratiques en matière de traitement des données et de mise à jour de l’application.
- MASVS-RESILIENCE : renforcer la résilience face au reverse engineering et de falsification.
Cette liste donne une bonne représentation des familles de vulnérabilités que nous pouvons identifier sur les applications mobiles.
En fonction du type d’application, les exigences en termes de sécurité vont varier, nous allons donc adapter les types de tests en fonction des besoins en termes de sécurité.
Dans la suite de cet article, nous ne présenterons pas de manière exhaustive toutes les vulnérabilités inhérentes aux applications mobiles mais celles que nous rencontrons le plus souvent lors de nos tests d’intrusion.
Stockage non sécurisé de données sensibles
En général, les applications mobiles ont besoin de stocker certaines données sur le téléphone afin de les conserver en mémoire. Il est fortement déconseillé de stocker directement le mot de passe de l’utilisateur sur le téléphone. Il est préférable d’utiliser un token de session à la place.
De plus, il est essentiel de gérer correctement le stockage de ce token de session sur le téléphone. Sur iOS, cela devrait être effectué à l’aide de la keychain, tandis que sur Android, le keystore est l’endroit approprié.
Malheureusement, il est fréquent de trouver des informations sensibles stockées de manière inadaptée, telles que dans les SharedPreferences sur Android, les NSUserDefaults sur iOS voire dans des bases de données SQLite.
Cependant, l’accès à ces données est complexe et nécessite généralement un accès physique à un téléphone rooté/jailbreaké.
Android dispose de 4 manières pour stocker les données : stockage spécifique à l’application, en base de données, dans les préférences et le stockage partagé.
Les 3 premiers ne sont accessibles qu’à l’application, contrairement au stockage partagé qui est accessible à toutes les applications.
Si une application Android utilise ce stockage pour des données sensibles, elles seront accessibles à tous et une application malveillante pourra les exfiltrer. Par exemple, imaginons une application qui sauvegarde le cache des requêtes HTTP dans les données partagées. Ce cache peut contenir des informations sensibles comme un token d’authentification. Ainsi, une application malveillante pourra donc exploiter cette vulnérabilité pour voler le token.
Un autre exemple qui marche sur iOS et Android est l’utilisation du répertoire Download. Si ce répertoire est utilisé, il faut garder en tête qu’une application malveillante pourra avoir accès à aux données qui s’y trouvent (factures par exemple). Même si cela n’est pas forcément une vulnérabilité en soi, il est important de limiter grandement l’utilisation du dossier download.
Divulgation d’informations sensibles via les logs
En règle générale, il est conseillé de ne pas enregistrer de journaux (logs) dans une application en production, ou du moins de garantir qu’aucun journal ne contienne d’informations sensibles telles que les mots de passe.
Avoir accès aux logs de l’application nécessite cependant d’avoir un accès physique à un téléphone. Par ailleurs, sur Android, il est aussi nécessaire d’activer le mode Débogage USB, qui implique l’activation du mode développeur.
Ainsi, admettons qu’une application stocke le token d’authentification de manière adapté. En revanche, si celui-ci est affiché dans les logs, un attaquant pourrait connecter le device sur son PC et récupérer le token en écoutant les logs.
La sécurité des communications réseau
Quand on parle de communications réseau, on pense souvent attaques de type Man in the Middle, où un attaquant va essayer de se faire passer pour le serveur auprès de l’application.
Plusieurs protections peuvent être implémentées sur les devices pour se prémunir au mieux de ces attaques :
Autoriser uniquement les connexions HTTPS
La restriction des connexions uniquement en HTTPS peut être mise en place sur Android en utilisant cleartextTrafficPermitted="false"
et sur iOS en activant NSAllowsArbitraryLoad="NO"
.
Cette mesure équivaut à l’implémentation de la directive HSTS (HTTP Strict Transport Security) que l’on retrouve sur les sites web classiques.
Cela permet de garantir que tous les échanges se dérouleront de manière sécurisée et empêche les attaquants de rediriger vers un site non sécurisé en plus de protéger des erreurs de configurations du serveur si celui-ci ne redirige pas les connexion HTTP en HTTPS.
Vérifier le certificat HTTPS
Il est important de s’assurer que le certificat est valide, approuvé par une autorité de certification et qu’il n’est pas autosigné. Cela complique voire empêche un attaquant de se mettre en position Man in the Middle.
Prenons par exemple Alice qui est sur un réseau non sécurisé et qui utilise une application qui communique bien en https mais qui ne vérifie le certificat. Bob peut générer son propre certificat autosigné et s’il arrive à se mettre en Man in the middle, il pourra usurper le serveur.
Certificate pinning
Il est possible d’aller plus loin dans la vérification des certificats grâce au certificate pinning. L’idée ici est de vérifier si le certificat est bien celui attendu. Cela rajoute une défense en profondeur pour s’assurer que la communication s’effectue bien avec le serveur attendu.
Pour plus d’informations, vous pouvez consulter notre article dédié qui détaille le principe et le fonctionnement de ce type de mécanisme :
Certificate et Public Key Pinning
Par ailleurs, ce dernier est conseillé dans le cadre d’une application mobile mature en sécurité, donc n’investissez pas énormément de temps dessus si vous démarrez.
Les permissions de l’application
Une application mobile doit dans certains cas demander des autorisations pour actions spécifiques (par exemple récupérer la localisation). Une bonne pratique de sécurité est de limiter les permissions au strict nécessaire.
De plus, il est recommandé de communiquer à l’utilisateur la nécessité de cette permission pour le bon fonctionnement de l’application. En effet, ici, le principe de moindre privilège doit être la norme.
Deep links sur Android
Les deep links sont des URI (Uniform Resource Identifier) prédéfinis qui offrent la possibilité d’accéder directement à une fonctionnalité spécifique d’une application mobile lors d’un clic. Cependant, leur utilisation peut engendrer des vulnérabilités potentielles en cas de mauvaise implémentation.
Transfert de données sensibles via deep links
Cela signifie que si une application malveillante est installée sur le mobile, celle-ci peut s’ouvrir à la place de l’application légitime.
myapp://reset-password/?code=THECODE
Admettons par exemple qu’on a un lien de réinitialisation de mot de passe de la forme suivante : Si l’application malveillante peut ouvrir ce même type de lien et est choisie par défaut alors elle peut récupérer le code et par exemple l’exfiltrer.
Utilisation dangereuse des paramètres transmis via les deep links
Ici, le problème ne vient pas du mode de transmission des données mais de l’utilisation des paramètres.
Prenons l’exemple suivant :
L’application ouvre les liens commençant par « myapp » et, en fonction des paramètres, réalise les actions associées. Parmi les actions on peut trouver l’action « deleteaccount » si bob arrive à faire accéder Alice au lien suivant via phishing par exemple :
myapp://deleteaccount
Cela aura pour effet de supprimer le compte.
Nous avons rédigé un article détaillé pour expliquer plus en profondeur ces problématiques :
Deep links : fonctionnement, vulnérabilités, attaques et bonnes pratiques sécurité
Données sensibles dans le code de l’application
Il est toujours possible de récupérer le code source d’une application, plus ou moins facilement en fonction des technologies. Il est donc important de ne pas stocker des données sensibles comme des clés SSH, des mots de passe, etc.
Prenons un cas concret. Lors d’un audit, nous avons découvert dans une application AWS Access Key ID and Secret ce qui nous a permis d’usurper un développeur et d’élever nos privilèges.
Le dépôt Github suivant permet de voir les secrets qui peuvent fuiter sur les applications mobiles :
https://github.com/streaak/keyhacks
De plus, l’application ne doit en aucun cas remplacer le serveur dans les vérifications de sécurité. Par exemple le token d’authentification ne doit pas être généré sur l’application, car cela peut conduire par exemple a des vols de comptes :
Vol de comptes via détournement de tokens d’authentification
Prise en charge d’anciennes versions iOS ou Android
Cette problématique est particulièrement préoccupante sur la plateforme Android, où la prise en charge d’anciennes versions du système d’exploitation est courante. Toutefois, en 2023, il est fortement recommandé de cibler à minima Android 8.1 pour bénéficier de mises à jour de sécurité significatives.
Selon les données d’Android Studio, cela permet à l’application de fonctionner sur environ 90 % des appareils. Ainsi, autoriser l’application à partir de cette version offre un équilibre judicieux entre sécurité et accessibilité.
Focus sur la vulnérabilité Android Janus
En 2017, une vulnérabilité importante a été découverte dans Android permettant de modifier le code de l’application sans modifier la signature (uniquement la signature V1). Cela peut permettre à un attaquant de fournir une application malveillante en apparence légitime. Pour s’en prémunir il faut uniquement prendre en charge les signature V2 et V3 sur Android.
La plupart du temps, la signature V1 est présente pour assurer la possibilité d’utiliser l’application sur de vieilles versions d’Android, inférieur à 7.
L’attaque Janus se déroule comme suit : lorsqu’une application présente une vulnérabilité à Janus, un attaquant est en mesure d’incorporer un fichier Dex malveillant à l’application sans altérer sa signature.
En conséquence, si un utilisateur télécharge l’application et possède déjà la version d’origine, cette modification sera perçue comme une simple mise à jour légitime.
Auteur : Thomas DELFINO – Pentester @Vaadata