En este artículo te voy a explicar cómo saltar el mecanismo SSL Pinning que se implementa para aplicaciones en Android y de este modo poder capturar tráfico SSL, datos de usuario, contraseñas y lo que desees. Para lograr este cometido, necesitaremos de varias cosas:
- Un dispositivo Android con acceso Root, puede ser un dispositivo físico o sencillamente uno corriendo en un emulador.
- Python instalado en nuestro sistema operativo.
- La herramienta Frida. Puedes instalarla usando el comando
pip install Frida objection frida-tools --user
una vez hayas instalado Python en tu sistema. - Burpsuite.
- Android Platform Tools, especialmente ADB.
- El script para la inyección a la aplicación móvil: puedes descargarlo desde este enlace de descarga o simplemente guardando el siguiente código como fridascript.js
/* Android SSL Re-pinning frida script v0.2 030417-pier $ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt $ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/ UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 ! */ setTimeout(function(){ Java.perform(function (){ console.log(""); console.log("[.] Cert Pinning Bypass/Re-Pinning"); var CertificateFactory = Java.use("java.security.cert.CertificateFactory"); var FileInputStream = Java.use("java.io.FileInputStream"); var BufferedInputStream = Java.use("java.io.BufferedInputStream"); var X509Certificate = Java.use("java.security.cert.X509Certificate"); var KeyStore = Java.use("java.security.KeyStore"); var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); var SSLContext = Java.use("javax.net.ssl.SSLContext"); // Load CAs from an InputStream console.log("[+] Loading our CA...") var cf = CertificateFactory.getInstance("X.509"); try { var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt"); } catch(err) { console.log("[o] " + err); } var bufferedInputStream = BufferedInputStream.$new(fileInputStream); var ca = cf.generateCertificate(bufferedInputStream); bufferedInputStream.close(); var certInfo = Java.cast(ca, X509Certificate); console.log("[o] Our CA Info: " + certInfo.getSubjectDN()); // Create a KeyStore containing our trusted CAs console.log("[+] Creating a KeyStore for our CA..."); var keyStoreType = KeyStore.getDefaultType(); var keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore..."); var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); var tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); console.log("[+] Our TrustManager is ready..."); console.log("[+] Hijacking SSLContext methods now...") console.log("[-] Waiting for the app to invoke SSLContext.init()...") SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) { console.log("[o] App invoked javax.net.ssl.SSLContext.init..."); SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c); console.log("[+] SSLContext initialized with our custom TrustManager!"); } }); },0);
¿Qué es SSL Pinning?
La mayoría de aplicaciones móviles implementan SSL Pinning ¿Por qué? Considera que quieres intercambiar algunos datos entre nuestro dispositivo y servidor de forma segura ¿El cifrado SSL hará que la transferencia de datos sea segura? Bueno, hay una trampa. Antes de la transferencia de datos, el cliente busca el certificado SSL del servidor y revisa si coincide con el nombre de host solicitado y la certificación raíz de confianza. Lo que no garantiza es que el certificado suministrado sea el certificado real proporcionado por el servidor para el nombre de host solicitado; por lo tanto, confiar en los certificados de confianza almacenados en el dispositivo no hará que la transferencia de datos sea "segura".
Certificate Pinning es una codificación del certificado en el que se confía en el servidor remoto dentro de la propia aplicación, de modo que ignorará el almacenamiento de certificados de confianza de los dispositivos y confiará en su propio certificado codificado que la aplicación utilizará para comunicarse con el servidor remoto de forma "segura".
Saltar la protección SSL Pinning es el paso más importante que debes hacer incluso cuando comenzamos el análisis dinámico de las solicitudes HTTP para la mayoría de las aplicaciones móviles hoy en día, ya que las organizaciones están más preocupadas por la privacidad de los datos y la transferencia segura de datos a través de la red para evitar ataques como por ejemplo Man In The Middle (MiTM).
¿Qué es Frida?
"Es un kit de herramientas de instrumentación de código dinámico. Le permite inyectar fragmentos de JavaScript o su propia biblioteca en aplicaciones nativas en Windows, macOS, GNU/Linux, iOS, Android y QNX. Frida también le proporciona algunas herramientas simples creadas sobre la API de Frida. Estos pueden usarse tal cual, ajustarse a sus necesidades o servir como ejemplos de cómo usar la API " - https://www.frida.re/docs/home/
Configuración del entorno e instalación
El primer paso que debes seguir, es activar la opción "USB Debugging" en nuestro dispositivo Android como se muestra a continuación:
- Activa las opciones de desarrollador en Android. Busca "Configuración -> Acerca del teléfono -> Software -> Presiona 8 veces seguidas encima de 'Número de compilación'", con eso estarán activadas.
- Activa la opción "USB Debugging" en "Configuración -> Opciones de desarrollador"

3. Busca la dirección IP local de tu celular.
4. Ve a la carpeta donde están los ejecutables de Android Plaftform Tools y ejecuta: adb connect IP_de_tu_celular:5555
. Ejemplo:
sechacklabs @ SecHackLabs ~
└─ ▶ adb connect 192.168.122.201:5555
* daemon not running; starting now at tcp:5037
* daemon started successfully
connected to 192.168.122.201:5555
5. Verifica que el dispositivo esté conectado con adb devices
sechacklabs @ SecHackLabs ~
└─ ▶ adb devices
List of devices attached
192.168.122.201:5555 device
6. Descarga el servidor Frida de acuerdo a la arquitectura de tu celular desde https://github.com/frida/frida/releases/ y luego extraígalo. Si no sabe cual es la arquitectura de su celular, ejecute el comando adb shell getprop ro.product.cpu.abi
sechacklabs @ SecHackLabs ~
└─ ▶ adb shell getprop ro.product.cpu.abi
x86_64
En nuestro caso descargamos frida-server-12.6.17-android-x86_64.xz
7. Instala la aplicación a la cual vas a saltar la protección SSL Pinning, en nuestro caso, usaremos Facebook. Abre la aplicación y déjala corriendo en segundo plano.
Configuración del servidor Frida
Necesitamos ejecutar el servidor Frida dentro del dispositivo antes de inyectar el script. Sigue estos pasos:
- Suba el archivo del servidor Frida descargado anteriormente con el comando
adb push ruta_a_la_carpeta_del_servidor_frida /data/local/tmp
sechacklabs @ SecHackLabs ~ └─ ▶ adb push Downloads/frida-server-12.6.17-android-x86_64 /data/local/tmp Downloads/frida-server-12.6.17-android-x86_64: 1 file pushed. 53.8 MB/s (52598088 bytes in 0.933s)
- De permisos de ejecución al archivo subido anteriormente con
adb shell chmod 777 /data/local/tmp/frida-server-12.6.17-android-x86_64
Configuración de Burpsuite
Para configurar Burpsuite, sigue los pasos detallados que se encuentran en https://support.portswigger.net/customer/portal/articles/1841101-config…
Obteniendo el certificado para interceptar el tráfico
El siguiente paso es exportar el certificado usado por Burpsuite, para ello vamos a "Proxy -> Options -> Proxy Listeners -> Import/Export CA Certificate"

Debemos elegir la ruta y guardarlo.
Colocando el certificado de Burpsuite en el dispositivo Android
Para poder interceptar el tráfico, el servidor Frida necesita tener acceso al certificado de Burpsuite así que usaremos el mismo certificado descargado en el paso anterior. Coloca el certificado en la misma ruta del dispositivo Android donde subimos el servidor Frida con el nombre cert-der.crt (Es importante colocarlo con ese nombre para no tener problemas al momento de ejecutar el servidor, en caso de que use otro nombre deberá cambiar la línea var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");
en el archivo fridascrypt.js
descargado al comienzo del artículo). Usamos el comando adb push ruta_al_certificado_descargado_de_burpsuite
sechacklabs @ SecHackLabs ~
└─ ▶ adb push cacert.der /data/local/tmp/cert-der.crt
cacert.der: 1 file pushed. 0.1 MB/s (973 bytes in 0.011s)
Saltando SSL Pinning usando el script de inyección fridascrypt.js
El momento de la verdadera magia ha llegado, inyectaremos fridascrypt.js
en la aplicación víctima.
- Copia
fridascrypt.js
en la misma ruta donde se encuentran el servidor Frida y el certificado de Burpsuite con el comandoadb push ruta_a_fridascrypt.js /data/local/tmp
sechacklabs @ SecHackLabs ~ └─ ▶ adb push fridascrypt.js /data/local/tmp/ fridascrypt.js: 1 file pushed. 0.3 MB/s (2881 bytes in 0.009s)
- Ejecuta el servidor Frida en el dispositivo con privilegios root.
sechacklabs @ SecHackLabs ~ └─ ▶ adb shell "su -c '/data/local/tmp/frida-server-12.6.17-android-x86_64 &'" [1] 4311
- Lista todos los procesos corriendo en nuestro dispositivo móvil usando desde nuestra PC el comando
frida-ps -U
y localiza la aplicación que vamos a inyectar, en este caso com.discord con PÏD 7490.
sechacklabs @ SecHackLabs ~ └─ ▶ frida-ps -U PID Name ---- -------------------------------------------------- 3929 adbd 1159 android.hardware.audio@2.0-service 1160 android.hardware.bluetooth@1.0-service.btlinux 1161 android.hardware.camera.provider@2.4-service 1162 android.hardware.cas@1.0-service 1163 android.hardware.configstore@1.0-service 1164 android.hardware.dumpstate@1.0-service 1165 android.hardware.light@2.0-service 1166 android.hardware.power@1.0-service 1167 android.hardware.usb@1.0-service 1168 android.hardware.wifi@1.0-service 1158 android.hidl.allocator@1.0-service 1176 audioserver 1177 cameraserver 1391 com.android.inputmethod.latin 1877 com.android.launcher3 1657 com.android.phone 1406 com.android.systemui 4820 com.android.vending 7490 com.discord 7647 com.facebook.katana 2082 com.google.android.gms 1969 com.google.android.gms.persistent 1807 com.google.android.googlequicksearchbox:interactor 7609 com.google.android.webview:s 1772 com.google.process.gservices 7987 com.tunnelworkshop.postern 1178 drmserver 4330 frida-helper-32 4311 frida-server-12.6.17-android-x86_64 1189 gatekeeperd 1169 healthd 1081 hwservicemanager 1 init 1179 installd 1380 ip6tables-restore 1379 iptables-restore 1180 keystore 1170 lmkd 4313 logcat 1079 logd 1200 mdnsd 1187 media.codec 1182 media.extractor 1183 media.metrics 1181 mediadrmserver 1184 mediaserver 1137 netd 1829 org.android_x86.analytics 1188 rild 1080 servicemanager 1173 sh 1185 storaged 1175 su 1171 surfaceflinger 1270 system_server 1172 thermalserviced 1190 tombstoned 1065 ueventd 1113 v86d 1082 vndservicemanager 1130 vold 1455 webview_zygote32 1186 wificond 1139 zygote 1138 zygote64
- Conecta fridascript.js dentro de la aplicación víctima con el comando
frida -U -l ruta_a_fridascrypt.js_en_su_pc -f nombre_de_la_aplicación --no-pause
ofrida --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f nombre_de_la_aplicación --no-pause
sechacklabs @ SecHackLabs ~ └─ ▶ frida -U -l fridascrypt.js -f com.discord --no-pause ____ / _ | Frida 12.6.17 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/ Spawned `com.discord`. Resuming main thread! [QEMU Standard PC (i440FX + PIIX, 1996)::com.discord]-> [.] Cert Pinning Bypass/Re-Pinning [+] Loading our CA... [o] Our CA Info: CN=PortSwigger CA, OU=PortSwigger CA, O=PortSwigger, L=PortSwigger, ST=PortSwigger, C=PortSwigger [+] Creating a KeyStore for our CA... [+] Creating a TrustManager that trusts the CA in our KeyStore... [+] Our TrustManager is ready... [+] Hijacking SSLContext methods now... [-] Waiting for the app to invoke SSLContext.init()... [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager! [o] App invoked javax.net.ssl.SSLContext.init... [+] SSLContext initialized with our custom TrustManager!
- ¡Ya está! Ahora todo el tráfico que pase por la aplicación será interceptado por Burpsuite como se puede ver a continuación:
Inicio de sesión Discord
Usuario y contraseña de Discord interceptados
Eso es todo lo que quería enseñarte, espero que haya sido de tu agrado. Si fue así, chatea con nosotros en Discord, registrate en el foro, síguenos en Facebook y Twitter, y no olvides compartirnos en las redes sociales, te lo agradecemos.
Acerca del autor

Especialista en Seguridad Informática. Fundador de Security Hack Labs. Desarrollador de BlackArch Linux y creador de Findomain. Twitter: @edu4rdshl XMPP: edu4rdshl@conversations.im Threema ID: 736WU8VV
- Inicie sesión para enviar comentarios