Le SSL pinning est la dernière ligne de défense des applications mobiles contre l'interception de trafic. En 2026, avec Android 15 qui durcit le modèle de sécurité réseau, le bypass SSL pinning est devenu plus complexe — mais pas impossible. Ce guide présente les techniques actuelles utilisées par les pentesters mandatés : de Frida aux modules Magisk, en passant par l'analyse statique de l'APK et la configuration Network Security Config, avec des exemples de code reproductibles et les contre-mesures pour les développeurs.

Le SSL pinning bypass Android 15 est l'un des défis techniques les plus récurrents dans les missions de test d'intrusion mobile. Chaque application bancaire, chaque app de santé, chaque outil d'entreprise digne de ce nom implémente aujourd'hui une forme de certificate pinning pour empêcher l'interception du trafic par un proxy comme Burp Suite. C'est une mesure de sécurité légitime et recommandée — notamment par l'OWASP Mobile App Security — qui force l'application à vérifier non seulement la validité du certificat TLS, mais aussi son identité spécifique. Le problème pour le pentester mandaté est précisément là : sans pouvoir intercepter le trafic de l'application, l'analyse des communications entre le client mobile et les API backend devient impossible. Android 15 a introduit de nouvelles restrictions réseau (Restricted Networking Mode) qui compliquent certaines approches traditionnelles. Mais l'écosystème des outils de bypass a évolué en parallèle. Ce guide détaille les techniques opérationnelles en 2026 : setup Frida, scripts de bypass OkHttp et TrustManager personnalisé, utilisation d'Objection, approches root-based avec Magisk, et configuration réseau transparente avec Burp Suite. Chaque technique est présentée avec ses avantages, ses limites, et les détections défensives correspondantes.

À retenir

  • Frida + scripts universels : la méthode la plus flexible pour bypasser le SSL pinning en 2026 — fonctionne sur la plupart des implémentations OkHttp, TrustKit et natives sans modifier l'APK.
  • Android 15 Restricted Networking Mode : les nouvelles restrictions réseau d'Android 15 impactent l'injection de proxy transparent ; contournement via adb reverse + ProxyDroid ou Network Security Config modifiée dans l'APK repackagé.
  • Objection framework : la commande android sslpinning disable bypass en une ligne les implémentations courantes — solution idéale pour un pentest rapide sur des cibles non obfusquées.
  • Analyse statique APK obligatoire : avant toute tentative dynamique, jadx-gui révèle le type d'implémentation (OkHttp, custom TrustManager, TrustKit) et guide le choix de la technique de bypass adaptée.
  • Root detection et anti-tampering : les apps modernes combinent SSL pinning avec détection root (SafetyNet/Play Integrity) — les bypasser séparément ne suffit plus ; il faut souvent les traiter simultanément.

Avertissement légal : Les techniques de bypass SSL pinning décrites dans cet article sont réservées aux pentesters mandatés disposant d'une autorisation écrite et aux chercheurs en sécurité mobile travaillant sur leurs propres applications. Utiliser ces techniques sur des applications sans autorisation constitue une infraction aux articles 323-1 et suivants du Code pénal. Ces méthodes sont présentées dans un cadre éducatif et défensif.

Comment fonctionne réellement le SSL Pinning sur Android ?

Comprendre ce qu'on cherche à bypasser est indispensable avant de choisir la technique. Il existe deux grandes familles de pinning :

Certificate Pinning : l'application vérifie que le certificat TLS présenté par le serveur correspond exactement au certificat (ou à un certificat d'une chaîne précise) stocké en dur dans l'application. Si vous injectez le certificat CA de Burp Suite, la chaîne de certificats change, et l'app rejette la connexion. C'est l'implémentation la plus courante dans les apps bancaires françaises.

Public Key Pinning : l'application vérifie uniquement le fingerprint de la clé publique du certificat. Plus flexible que le certificate pinning (résiste aux renouvellements de certificat tant que la clé ne change pas), mais le principe de bypass est identique.

Les implémentations concrètes en Android :

  • OkHttp CertificatePinner : la plus répandue. La vérification est dans la classe CertificatePinner d'OkHttp.
  • TrustKit-Android : bibliothèque de DataTheoem qui lit la configuration depuis un fichier XML.
  • Android Network Security Config : mécanisme natif Android configurable en XML, depuis Android 7.0.
  • Custom TrustManager : implémentation maison d'un X509TrustManager avec pinning intégré — la plus difficile à bypasser dynamiquement car le code est unique à chaque app.

Analyse statique APK avec apktool et jadx-gui

Avant toute tentative de bypass dynamique, l'analyse statique de l'APK révèle le type d'implémentation et guide la stratégie. Cette étape économise beaucoup de temps.

# Extraction de l'APK depuis un device connecté
adb shell pm list packages | grep "nom.app"
adb shell pm path com.exemple.app
adb pull /data/app/com.exemple.app-1/base.apk /tmp/target.apk

# Décompilation avec apktool (ressources + smali)
apktool d /tmp/target.apk -o /tmp/target-decompiled/

# Vérifier le Network Security Config
cat /tmp/target-decompiled/res/xml/network_security_config.xml

# Rechercher les références au pinning dans le code smali
grep -r "CertificatePinner\|TrustKit\|ssl_pins\|certificate_pins" /tmp/target-decompiled/smali/

# Décompilation Java avec jadx (interface graphique)
jadx-gui /tmp/target.apk

# Ou en ligne de commande jadx
jadx -d /tmp/target-jadx/ /tmp/target.apk

# Rechercher les classes de pinning dans le code Java décompilé
grep -r "OkHttpClient\|CertificatePinner\|TrustManager\|checkServerTrusted" /tmp/target-jadx/sources/

Dans jadx-gui, chercher les classes qui implémentent X509TrustManager ou qui référencent CertificatePinner. Le code Java décompilé révèle souvent les hashes SHA-256 des certificats pinnés — information précieuse pour comprendre la chaîne de confiance attendue.

Frida : setup et bypass SSL pinning en 2026

Frida est le framework d'instrumentation dynamique de référence. Il permet d'injecter du JavaScript dans un processus Android en cours d'exécution et de hooker n'importe quelle méthode Java ou native.

# Installation de frida-tools côté machine de l'attaquant
pip install frida-tools

# Télécharger frida-server pour l'architecture du device (ARM64 pour la plupart)
# Vérifier l'architecture du device
adb shell getprop ro.product.cpu.abi
# arm64-v8a → télécharger frida-server-XX.X.X-android-arm64

# Pousser frida-server sur le device
adb push frida-server-16.2.1-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server

# Démarrer frida-server sur le device (nécessite root)
adb shell su -c "/data/local/tmp/frida-server &"

# Vérifier la connexion
frida-ps -U

# Lancer l'app avec frida et un script de bypass
frida -U -f com.exemple.app -l /tmp/ssl-bypass.js --no-pause

Le script de bypass universel couvrant OkHttp, TrustManager custom et les implémentations natives :

/**
 * SSL Pinning Bypass — Frida Script Universal 2026
 * Couvre: OkHttp CertificatePinner, X509TrustManager custom, TrustKit
 * Usage: frida -U -f com.app.target -l ssl-bypass.js --no-pause
 */

Java.perform(function() {
    console.log("[*] SSL Pinning Bypass — démarrage");

    // ===== 1. Bypass OkHttp CertificatePinner =====
    try {
        var CertificatePinner = Java.use("okhttp3.CertificatePinner");
        CertificatePinner.check.overload("java.lang.String", "java.util.List").implementation = function(hostname, peerCertificates) {
            console.log("[+] OkHttp CertificatePinner.check() bypassed pour: " + hostname);
            return;
        };
        CertificatePinner.check.overload("java.lang.String", "[Ljava.security.cert.Certificate;").implementation = function(hostname, certs) {
            console.log("[+] OkHttp CertificatePinner.check() (v2) bypassed pour: " + hostname);
            return;
        };
    } catch(e) {
        console.log("[-] OkHttp CertificatePinner non trouvé: " + e.message);
    }

    // ===== 2. Bypass X509TrustManager custom =====
    try {
        var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager");
        var SSLContext = Java.use("javax.net.ssl.SSLContext");

        var TrustManager = Java.registerClass({
            name: "com.bypass.TrustManager",
            implements: [X509TrustManager],
            methods: {
                checkClientTrusted: function(chain, authType) {},
                checkServerTrusted: function(chain, authType) {
                    console.log("[+] checkServerTrusted bypassed");
                },
                getAcceptedIssuers: function() { return []; }
            }
        });

        var TrustManagers = [TrustManager.$new()];
        var sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, TrustManagers, null);
        var defaultSSLSocketFactory = sslContext.getSocketFactory();

        var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
        HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
        HttpsURLConnection.setDefaultHostnameVerifier(
            Java.use("javax.net.ssl.HttpsURLConnection").getDefaultHostnameVerifier()
        );
        console.log("[+] X509TrustManager bypassed");
    } catch(e) {
        console.log("[-] TrustManager bypass error: " + e.message);
    }

    // ===== 3. Bypass HostnameVerifier =====
    try {
        var HostnameVerifier = Java.use("javax.net.ssl.HostnameVerifier");
        var AllHostsValid = Java.registerClass({
            name: "com.bypass.AllHostsValid",
            implements: [HostnameVerifier],
            methods: {
                verify: function(hostname, session) {
                    console.log("[+] HostnameVerifier.verify() → true pour: " + hostname);
                    return true;
                }
            }
        });
        var HttpsURLConnection2 = Java.use("javax.net.ssl.HttpsURLConnection");
        HttpsURLConnection2.setDefaultHostnameVerifier(AllHostsValid.$new());
    } catch(e) {
        console.log("[-] HostnameVerifier bypass error: " + e.message);
    }

    console.log("[*] SSL Pinning Bypass — scripts injectés");
});

Objection Framework : bypass en une commande

Objection est construit sur Frida et automatise les tâches de pentest mobile les plus communes. Pour les implémentations de pinning non obfusquées, c'est la solution la plus rapide :

# Installation
pip install objection

# Lancement (frida-server doit être actif sur le device)
objection -g com.exemple.app explore

# Dans le shell Objection — bypass SSL pinning
android sslpinning disable

# Autres commandes utiles en pentest mobile
android root disable            # Bypass détection root basique
android hooking list classes    # Lister toutes les classes chargées
android hooking watch class com.exemple.app.network.ApiClient  # Surveiller une classe
android intent launch_activity com.exemple.app/.ui.LoginActivity

# Dump des préférences partagées (stockage de credentials)
android preferences get
android keystore list

# Quitter l'explore et patcher directement l'APK (injection frida sans root)
objection patchapk -s /tmp/target.apk

La commande objection patchapk est particulièrement intéressante : elle réemballe l'APK en injectant le gadget Frida, permettant d'utiliser Frida sur un device non rooté. L'APK patché doit être resigné et réinstallé — ce qui déclenche parfois des détections anti-tampering.

Android 15 change-t-il vraiment les règles du bypass SSL Pinning ?

Android 15 a introduit plusieurs changements qui compliquent le bypass SSL pinning par rapport aux versions précédentes :

Restricted Networking Mode (MODE_NETWORK_NONE) : les applications peuvent désormais déclarer qu'elles n'ont besoin d'aucune connexion réseau en dehors de leurs propres processus. En pratique, cela bloque les proxys transparents qui redirigent le trafic au niveau réseau — ProxyDroid ne fonctionne plus dans ce contexte.

Renforcement de la Network Security Config : Android 15 ignore les Network Security Configs qui n'utilisent pas le bon namespace XML et durcit l'application des règles de trust. Les anciennes astuces de manipulation du network_security_config.xml via apktool nécessitent maintenant de signer l'APK avec une clé valide et d'éviter les vérifications d'intégrité.

L'XML de Network Security Config modifiée pour accepter les CAs utilisateur (solution pour les devices non rootés) :

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!-- Accepter les CAs installées par l'utilisateur (pour Burp Suite) -->
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <!-- Autoriser les CAs utilisateur (désactivé par défaut depuis Android 7) -->
            <certificates src="user"/>
        </trust-anchors>
    </base-config>

    <!-- Configuration spécifique pour les domaines API -->
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">api.exemple.com</domain>
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
        <!-- Commenter ou supprimer le bloc pin-set pour désactiver le pinning -->
        <!-- <pin-set>
            <pin digest="SHA-256">hash_du_certificat==</pin>
        </pin-set> -->
    </domain-config>
</network-security-config>

ProxyDroid et Burp Suite : setup proxy transparent pour Android 15

La configuration d'interception avec Burp Suite reste l'objectif final. La méthode recommandée en 2026 sur Android 15 :

# Côté machine pentest — Burp Suite écoute sur 0.0.0.0:8080
# Configurer le Proxy Listener dans Burp : All Interfaces, port 8080

# Exporter le certificat CA Burp Suite
# Burp → Proxy → Options → Import/Export CA Certificate → Certificate in DER format → Save

# Convertir en PEM pour Android
openssl x509 -inform DER -in cacert.der -out cacert.pem
openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1
# Exemple de résultat: 9a5ba575
cp cacert.pem 9a5ba575.0

# Sur device Android 15 rooté — installer le certificat en tant que system CA
adb push 9a5ba575.0 /data/local/tmp/
adb shell su -c "mount -o remount,rw /system"
adb shell su -c "cp /data/local/tmp/9a5ba575.0 /system/etc/security/cacerts/"
adb shell su -c "chmod 644 /system/etc/security/cacerts/9a5ba575.0"
adb shell su -c "mount -o remount,ro /system"

# Configuration du proxy ADB (plus fiable que WiFi settings sur Android 15)
adb shell settings put global http_proxy 192.168.1.10:8080

# Ou via redirection de port (pour apps avec proxy detection)
adb reverse tcp:8080 tcp:8080
# L'app cible se connecte à localhost:8080 → redirigé vers Burp sur la machine pentest

Magisk et TrustMeAlready : bypass basé sur le root

Pour les engagements sur des devices rootés avec Magisk, l'approche la plus puissante combine plusieurs modules :

# Vérifier que Magisk est installé et actif
adb shell su -c "magisk -v"

# Installer le module MagiskTrustUserCerts (monte les certs user dans system)
# Télécharger MagiskTrustUserCerts.zip depuis GitHub releases
adb push MagiskTrustUserCerts.zip /data/local/tmp/
# Installer via Magisk Manager : Modules → Install from storage

# Alternative : TrustMeAlready (Xposed/LSPosed module)
# Installe le certificat Burp comme system CA via hook Xposed
# Framework LSPosed requis (remplace EdXposed sur Android 12+)

# Vérification post-installation
adb shell su -c "ls /system/etc/security/cacerts/ | grep -i burp"

# Désactiver SafetyNet/Play Integrity pour éviter blocage app
# Module Magisk : MagiskHide Props Config ou Universal SafetyNet Fix
adb shell su -c "magiskpolicy --live 'permissive *'"

MITMProxy comme alternative à Burp Suite

MITMProxy est une alternative open source à Burp Suite, particulièrement adaptée lorsque l'on souhaite scripter des tests d'interception en Python. Son mode transparent et ses add-ons permettent d'automatiser des analyses répétitives que Burp imposerait de réaliser manuellement. Pour le pentest mobile, l'approche est similaire à Burp : injecter le certificat CA dans les system certificates du device, puis rediriger le trafic.

# Installation MITMProxy
pip install mitmproxy

# Mode interactif (interface TUI)
mitmproxy --listen-host 0.0.0.0 --listen-port 8080

# Mode transparent (nécessite iptables ou tproxy)
mitmproxy --mode transparent --listen-port 8080

# Mode headless avec script Python
mitmdump -s /tmp/intercept_api.py --listen-port 8080

# Exporter le certificat CA mitmproxy pour l'installer sur Android
# Après premier lancement, le cert est dans ~/.mitmproxy/mitmproxy-ca-cert.pem
openssl x509 -inform PEM -subject_hash_old -in ~/.mitmproxy/mitmproxy-ca-cert.pem | head -1
# Ex: c8750f0d → renommer en c8750f0d.0 et pousser vers /system/etc/security/cacerts/

Un exemple de script MITMProxy pour capturer automatiquement les tokens JWT dans les en-têtes Authorization :

"""
Script mitmproxy pour extraire les tokens JWT des requêtes mobiles
Usage: mitmdump -s extract_jwt.py --listen-port 8080
"""
import json, base64
from mitmproxy import http

def request(flow: http.HTTPFlow) -> None:
    auth = flow.request.headers.get("Authorization", "")
    if auth.startswith("Bearer "):
        token = auth[7:]
        parts = token.split(".")
        if len(parts) == 3:
            try:
                payload = json.loads(base64.b64decode(parts[1] + "=="))
                print(f"[JWT] {flow.request.pretty_host}: {json.dumps(payload, indent=2)}")
            except Exception:
                pass

Commandes ADB essentielles pour mobile pentest

Maîtriser ADB (Android Debug Bridge) est indispensable pour tout pentest mobile. Les commandes les plus utiles :

# Informations sur le device connecté
adb devices -l
adb shell getprop ro.build.version.release    # Version Android
adb shell getprop ro.product.model            # Modèle
adb shell getprop ro.build.version.security_patch  # Niveau de correctif sécurité

# Gestion des applications
adb shell pm list packages -f | grep "mot-cle"
adb shell pm path com.exemple.app
adb pull /data/app/com.exemple.app-1/base.apk /tmp/
adb install -r /tmp/patched-app.apk           # Réinstaller APK modifié

# Logs en temps réel (filtrer sur le tag de l'application)
adb logcat -s "com.exemple.app"
adb logcat | grep -i "ssl\|certificate\|trust\|pinning"
adb logcat -v time > /tmp/logcat-session.txt

# Port forwarding pour proxy interception
adb forward tcp:8080 tcp:8080
adb reverse tcp:8080 tcp:8080

# Accès shell et extraction de données
adb shell
adb shell run-as com.exemple.app ls /data/data/com.exemple.app/  # App non-rootée
adb shell su -c "cat /data/data/com.exemple.app/shared_prefs/*.xml"  # Rooté

# Capture d'écran et enregistrement
adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png /tmp/
adb shell screenrecord /sdcard/demo.mp4 --time-limit 60
adb pull /sdcard/demo.mp4 /tmp/

# Monkey testing (stress test UI)
adb shell monkey -p com.exemple.app -v 500

Que dit l'OWASP Mobile Top 10 2024 sur le SSL Pinning ?

L'OWASP Mobile App Security situe le SSL pinning dans un contexte de contrôles de sécurité mobile plus large. Deux catégories du Mobile Top 10 2024 sont directement concernées :

M3 — Insecure Authentication/Authorization : les tokens d'authentification transmis via des connexions non sécurisées (ou interceptables) sont exposés. Un bypass SSL pinning réussi permet d'observer ces tokens, de les rejouer, et d'analyser les failles d'autorisation au niveau des API. La mission de pentest mobile inclut systématiquement l'analyse de la gestion des sessions post-bypass.

M5 — Insufficient Cryptography : une implémentation défaillante du SSL pinning (comparaison de hashes incorrecte, gestion d'exceptions trop permissive dans les blocs catch) constitue une défaillance cryptographique. Les apps qui implémentent le pinning avec un try/catch vide autour de la vérification — une erreur de développement fréquente — sont bypassables sans Frida.

Pour les missions de bug bounty incluant des apps mobiles Android, consultez notre article sur les stratégies bug bounty 2026. Pour les techniques d'IA appliquées au pentest automatisé, voir notre article sur l'IA générative et le pentest automatisé.

Tableau comparatif des méthodes de bypass SSL pinning

Méthode Root requis Complexité Fonctionne sur Android 15 Détectable Idéal pour
Frida (script universel) Oui Moyenne Oui Oui (anti-Frida) Implémentations complexes, custom TrustManager
Objection Non (patchapk) Faible Oui Oui (anti-tampering) Apps standard, reconnaissance rapide
Magisk + MagiskTrustUserCerts Oui (Magisk) Faible Oui Play Integrity Device de test dédié, contournement système
Network Security Config patché Non Moyenne Partiellement Vérification signature Apps sans anti-tampering, phase statique
MITMProxy + transparent Non (WiFi) Faible Non (restrictions Android 15) Faible Apps sans pinning ou Network Security Config permissive

Questions fréquentes

Frida fonctionne-t-il sur toutes les versions d'Android 15 ?

Frida fonctionne sur Android 15 mais nécessite que le device soit rooté ou que l'APK soit patché avec le gadget Frida (via objection patchapk). Certaines ROMs Android 15 avec des patches de sécurité récents peuvent bloquer l'injection Frida via des mécanismes SELinux renforcés. Dans ce cas, utiliser Magisk avec le module MagiskDenyList désactivé pour l'app cible.

Comment bypasser le SSL pinning sans root sur Android 15 ?

Sans root, deux options : (1) objection patchapk qui réemballe l'APK avec le gadget Frida intégré — l'APK doit être désinstallé, resigné, et réinstallé sans vérification de signature (adb install -r --no-streaming) ; (2) modifier le network_security_config.xml via apktool pour autoriser les CAs utilisateur, puis repackager et resigné l'APK. Les deux approches échouent si l'application vérifie son intégrité (Google Play Integrity API).

Comment les développeurs peuvent-ils rendre le SSL pinning bypass-resistant ?

Combiner plusieurs défenses : implémentation de Certificate Pinning avec OkHttp (hash SHA-256 de la clé publique, pas du certificat entier) + détection Frida (vérification de la présence de frida-server dans la liste des processus) + Play Integrity API pour garantir l'intégrité de l'app + obfuscation du code avec R8/ProGuard pour compliquer l'analyse statique. Aucune défense n'est parfaite, mais empiler les couches augmente significativement le coût d'un bypass.

Quel est le lien entre SSL pinning et les tests OWASP MASVS ?

L'OWASP Mobile Application Security Verification Standard (MASVS) Level 2 exige l'implémentation du SSL pinning (contrôle MASVS-NETWORK-2). Un test MASVS L2 complet inclut donc obligatoirement la tentative de bypass SSL pinning. Les apps ciblant des niveaux de sécurité élevés (banques, santé, apps gouvernementales) doivent résister aux techniques de bypass documentées dans ce guide.

Peut-on bypasser le SSL pinning avec mitmproxy comme alternative à Burp ?

MITMProxy est une alternative open source crédible. Son addon ssl_strip et le mode transparent mitmproxy --mode transparent fonctionnent pour les apps sans pinning. Pour bypasser le pinning, les mêmes techniques s'appliquent (injection CA en system, Frida) — l'outil proxy importe peu. MITMProxy a l'avantage d'un scripting Python plus accessible que l'API Java de Burp pour automatiser des tests répétitifs.

Conclusion

Le SSL pinning bypass sur Android 15 n'est pas une technique unique — c'est une chaîne de décisions techniques : analyser l'implémentation avec jadx, choisir la méthode adaptée (Frida pour le custom, Objection pour le standard, Magisk pour le root-based), gérer les interactions avec la détection root et l'anti-tampering. En 2026, les apps les plus sécurisées combinent plusieurs niveaux de défense que le pentester doit aborder méthodiquement plutôt que de chercher une solution universelle.

Les techniques présentées ici s'inscrivent dans un cadre de pentest mobile plus large : voir notre article sur la sécurité mobile offensive Android et iOS pour les phases de test d'intrusion complètes, et notre guide sur le OSINT 2026 pour la phase de reconnaissance préalable à tout engagement mobile. L'ANSSI publie également des recommandations sur la sécurité des applications mobiles dans le cadre de NIS 2.

Vous souhaitez faire auditer la sécurité de votre application mobile Android ou iOS ? Nos pentesters certifiés réalisent des tests d'intrusion mobile complets couvrant le bypass SSL pinning, l'analyse statique APK, et les tests d'API backend. Contactez-nous pour un audit mobile conforme aux référentiels OWASP MASVS et PTES.