Dans le cadre de tests d’intrusion, il est régulièrement demandé aux auditeurs de trouver l’introuvable, de contourner l’incontournable. En effet, certaines applications ressemblent plus à des TP qu’à de vraies applications mais certaines d’entre elles intègrent des éléments de sécurité relativement avancés.
Parfois, il s’avère également que l’application a déjà été audité. Dans ce cas, il est probable que les bonnes recommandations soient déjà en place.
Néanmoins, l’auditeur est l’audité joue toujours au même jeu, celui du chat et de la souris et il n’est pas rare dans le cadre des tests d’intrusion mobiles que le chat gagne.
Voici un petit retour d’expérience sur l’audit d’une application client, la présentation des mécanismes de sécurité mis en place et les méthodes de contournement.
- Détection du root / jailbreak du périphérique
Bien qu’il ne soit pas bien compliqué dans la plupart des cas de contourner ce mécanisme de sécurité, empêcher l’application de s’exécuter sur un périphérique rooté / jailbreaké fait partie des meilleures pratiques de sécurité recommandées par l’OWASP.
En effet, au sein d’un périphérique rooté, un attaquant est en mesure d’accéder à l’ensemble des données de l’application, des fichiers potentiellement sensibles, modifier l’application en mémoire, etc.
Mais alors pourquoi mettre en place ce mécanisme s’il est possible de le contourner ? Comme le précise l’OWASP (lien ci-dessus), la mise en place de plusieurs contrôles de détection de root / jailbreak au sein de l’application va améliorer la sécurité globale en ralentissant les attaquants et en poussant les moins motivés/compétents à s’en prendre à une autre application.
Pour contourner cela, il est possible de décompiler l’application, d’éditer le code Smali puis de recompiler l’application. Néanmoins, cette technique bien que très efficace est relativement longue à mettre en place et peut demander plusieurs allers-retours avant de supprimer l’ensemble des vérifications. Pressé par le temps, nous allons utiliser Frida.
Frida est un outil d’analyse dynamique de code binaire modulaire. Le fonctionnement général de Frida est le suivant : du code est injecté dans le processus à analyser, celui-ci peut alors manipuler l’état de la cible et dialoguer avec un processus maître extérieur.
L’intérêt principal de Frida est donc de permettre l’interception d’appels à certaines fonctions, API ou méthodes. Une fois l’appel intercepté, l’utilisateur peut alors choisir d’étudier les arguments passés à l’appel, étudier l’état du processus, modifier les arguments, appeler une autre fonction, modifier la valeur de retour, etc.
L’installation de Frida n’étant pas décrite ici, il est possible de se référer au lien suivant.
Une fois Frida installé et le script de bypass de root exécuté, il est possible de voir que le message d’erreur change indiquant que la première protection vient de céder.
- Certificate Pinning
Comme il est possible de le voir sur la capture précédente, le message d’erreur vient de changer. Ce dernier indique que l’application (transitant via notre Burp, NDLR) n’est pas en mesure d’accéder à Internet.
Ce cas de figure doit rapidement faire penser l’auditeur à du Certificate Pinning. Le Certificate Pinning est une méthode permettant de vérifier le certificat du serveur côté client.
Cette vérification exige que le certificat du serveur ou son empreinte soit préalablement connu de l’application mobile.
Lors de l’établissement d’une connexion avec le serveur, l’application compare l’empreinte avec le certificat du serveur distant.
- Si les empreintes sont identiques, la connexion est valide et le transfert de données peut se poursuivre
- Si les empreintes ne sont pas identiques, l’application rejette la connexion
Le fait de faire transiter nos connexions par Burp ne va pas permettre la validation du certificat. Il est donc nécessaire de trouver un nouveau moyen de contournement. Comme précédemment, deux techniques existent et nous allons toujours utiliser la deuxième, après tout elle marche très bien.
De nombreuses méthodes permettant de contourner le Certificate Pinning existent, notamment grâce à l’utilisation de Frida.
Néanmoins, le fait que Frida soit déjà utilisée pour le contournement de la détection root, il peut être complexe (et surtout lent) de combiner les différents scripts. Rappelons-nous que nous n’avons que peu de temps, il faut faire les tests ainsi que le rapport.
Pour cela, il est alors possible d’utiliser frida-inject. frida-inject permet d’injecter à la volée des commandes au sein d’une application sans avoir besoin d’un client (pas besoin de pip install frida-tools). Il est donc nécessaire d’installer la bonne version (identique au serveur) de frida-inject sur le périphérique :
# wget https://github.com/frida/frida/releases/download/14.2.18/frida-inject-14.2.18-android-x86.xz
# unxz frida-inject-14.2.18-android-x86.xz
# mv frida-inject-14.2.18-android-x86 frida-inject
# adb push frida-inject /data/local/tmp/
Il ne reste plus qu’à uploader notre script de contournement de Certificate Pinning sur le périphérique (adb push ssl_pinning_bypass.js /sdcard)
Puis de l’exécuter grâce à la commande suivante (sur le périphérique) :
# cd /data/local/tmp
# chmod +x frida-inject
# ./frida-inject -n XXXXXXXX -s /sdcard/ssl_pinning_bypass.js
Dès lors, les messages d’erreur disparaissent et laissent place à une page blanche de l’application (en vrai, il y a le logo du client) :
On progresse, on progresse !
- Vérification du User-Agent
On progresse, on progresse mais l’application ne se lance toujours pas et ne reçoit aucune réponse à sa requête comme si cette dernière avait été supprimée par un WAF (pour rappel, c’est grâce à la suppression des paquets par des firewalls que Nmap est en mesure de dire que le port est filtré, car il ne reçoit aucune réponse) :
De plus, ce comportement est d’autant plus étrange que la même requête fonctionne parfaitement sur un navigateur. Ainsi, si le navigateur (par le biais du User Agent) est bien la cause de nos soucis, il est possible de supprimer automatiquement ce dernier dans les requêtes émises (ou de le modifier pour un User-Agent accepté bien sûr) directement dans le Match and Replace de Burp.
Dès lors que le User Agent est correctement modifié, l’accès à l’application se fait sans aucun problème :
- Une commande pour les exécuter tous
Si l’on souhaite exécuter l’ensemble des scripts en même temps (d’autres protections auraient pu être présente), il est possible de boucler sur frida-inject de la manière suivante :
for f in $(ls /sdcard/*js)
do
./frida-inject -p $(pidof XXXX) -s $f –eternalize
done
- Conclusion
J’ai souvent l’habitude de dire aux pentesters mais également aux développeurs qu’un gros problème n’est jamais que l’accumulation de plusieurs problèmes simples. N’hésitez pas à décomposer vos problèmes par étapes et contourner ces dernières une à une.