Analyser les communications entre une appli Android et son API

J’étais curieux de savoir comment Uber et d’autres applications similaires mettaient en œuvre leurs APIs, et quel type de données sont envoyées de mon téléphone vers ces APIs, alors je me suis penché sur la question.

Cet article est un petit résumé de mon voyage dans la rétro-ingénierie de l’application Uber Eats pour exposer ses communications.

Outils utilisés

  • Charles Proxy (http://www.charlesproxy.com/) pour analyser les paquets réseau
  • openssl pour créer ma propre autorité de certification
  • apktools pour ouvrir les fichiers apk
  • jarsigner pour signer l’application après sa reconstruction
  • adb pour communiquer avec mon téléphone

Mon téléphone fonctionne avec Android Nougat et il est rooté.


Préparation côté ordinateur

Création d’un CA (Certificate Authority)

Nous devons créer notre propre autorité de certification et la donner à Charles Proxy pour lui permettre de générer des certificats lorsque cela est nécessaire.

Générer le CA

mkdir certificates && cd certificates
openssl req -x509 -days 730 -nodes -newkey rsa:2048 -outform der -keyout server.key -out ca.der -extensions v3_ca

Convertir la PrivateKey

openssl rsa -in server.key -inform pem -out server.key.der -outform der
openssl pkcs8 -topk8 -in server.key.der -inform der -out server.key.pkcs8.der -outform der -nocrypt

Commandes empruntées à un excellent article de Awakened.

Side note: Si vous êtes sur MacOS, vous aurez probablement un problème avec openssl req [...], vous devez ajouter les lignes suivantes à la fin de /etc/ssl/openssl.cnf:

[ v3_ca ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

Faire du CA un CA de confiance sur Android

Pour que les applications fassent confiance à l’autorité de certification, nous devons soit la considérer comme une autorité de certification de confiance (téléphone rooté), soit modifier la configuration de l’application pour qu’elle fasse confiance aux certificats utilisateur (dans le xml de configuration lors du dépaquetage de l’application) et dans ce cas, suivre ce tutoriel.

Nous procéderons à l’ajout du certificat en tant que certificat de confiance.

Convertir la PublicKey (changer a58355c2.0 avec le résultat de la ligne 2)
openssl x509 -inform der -in ca.der -out ca.pem
openssl x509 -inform PEM -subject_hash_old -in ca.pem | head -1
cp ca.pem a58355c2.0
openssl x509 -inform PEM -text -in ca.pem -out /dev/null>> a58355c2.0
Copier le CA sur le téléphone Android
adb push a58355c2.0 /data/local/tmp
adb shell
Dans le Shell ADB
su
mount -o rw,remount /system
mv /data/local/tmp/a58355c2.0 /system/etc/security/cacerts/
chown root:root /system/etc/security/cacerts/a58355c2.0
chmod 644 /system/etc/security/cacerts/a58355c2.0
reboot

Dans Charles Proxy

Il suffit d’importer la clé privée dans Charles Proxy comme suit :

Creation du fichier p12
openssl pkcs12 -export -out MyCert.p12 -inkey server.key -in ca.pem

Et naviguez jusqu’à Proxy > Paramètres de proxy SSL > Root Certificate, puis sélectionnez le fichier p12 et nous pouvons continuer.


Écouter les paquets réseau à partir d’une application

Sur le téléphone, nous devons définir notre ordinateur comme proxy dans les paramètres.

Chaque paquet arrivant ou partant de notre téléphone est désormais intercepté par Charles Proxy. Comme nous avons ajouté notre propre CA en tant que CA de confiance sur le téléphone, nous devrions être en mesure de voir tout le trafic en clair, même sur les pages HTTPS du navigateur.

Cependant, cela n’est pas vrai pour de nombreuses applications, en particulier pour Uber Eats. Ces applications utilisent une technologie appelée “SSL Pinning”. En bref, l’application stocke la signature du certificat utilisé pour l’API de l’entreprise (comme api.uber.com). Cela signifie que l’authenticité du certificat est vérifiée chaque fois que l’application est ouverte, et que l’application refusera de se connecter à l’API si les signatures du certificat (actif et stocké) ne correspondent pas.

Notre certificat est utilisé alors que l’application Uber Eats attend son propre certificat.

Pour contourner ce problème, nous devons ouvrir le paquet apk de l’application et trouver un moyen de désactiver le SSL Pinning.

Ouverture du fichier APK de l’application
apktool d -f -r ubereats.apk

Ensuite, essayez de trouver dans les fichiers dépackagés une ligne contenant : const-string v4, "sha256/, la signature du certificat devrait être placée juste après.

Il vous suffit de mettre votre signature de certificat Root Charles à la place de celle-ci, et l’application Uber Eats acceptera la communication passant par Charles.

Reconstitution du fichier APK

Nous devons maintenant repackager l’application dans un fichier apk :

apktool b --use-aapt2 ubereats/ -o ubereats_unsigned.apk

Ce fichier apk n’est pas signé, et Android ne permettra pas son installation.

Nous allons donc générer une clé et l’utiliser pour signer l’apk :

keytool -genkey -v -keystore ubereats-key.keystore -alias ubereatskey -keyalg RSA -keysize 2048 -validity 10000
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ubereats-key.keystore ubereats_unsigned.apk ubereatskey
mv ubereats_unsigned.apk ubereats.apk
Réinstaller l’APK

Supprimez d’abord l’application de votre téléphone. Comme la signature est différente, si l’application est toujours présente lors de l’installation de notre propre version, Android peut émettre des erreurs parce que les signatures ne correspondent pas.

Avec ADB:

adb install ubereats.apk

Commencer à écouter

Maintenant que tout est en place, il suffit de lancer l’application et vous verrez les paquets en clair dans Charles Proxy.

N’oubliez pas de définir votre ordinateur comme proxy dans les paramètres de votre téléphone !