FRIDA I – Android SSL Pinning Bypass

Recursos

Para este post se utilizan los siguientes recursos:

  • Windows 10 Pro Versión 1809
  • Emulador Oficial de Android +info
  • Android Versión 6 – API 23 – x86
  • Python 2.7.9 Descarga Oficial
  • Frida 12.2.27 +info
  • ADB Tools +info

En caso de utilizar un smartphone Android físico deberá estar rooteado, en caso contrario se puede insertar la librería de Frida dentro de la app y volver a empaquetarla, esto se puede hacer automáticamente con Objection https://github.com/sensepost/objection

 

Instalación y puesta en marcha de Frida

Nuestro primer paso será instalar Frida (si no lo tenemos instalado). Para ello podemos utilizar de una manera muy sencilla el gestor de paquetes de Python PIP

python -m pip install frida-tools

Para el siguiente paso es importante conocer la arquitectura de nuestro terminal/emulador Android, para asegurarnos de ello podemos ejecutar el siguiente comando adb

adb.exe shell getprop ro.product.cpu.abi

Como en nuestro caso estamos utilizando un emulador basado en x86 tendremos que buscar el server de Frida que se corresponda a la arquitectura utilizada.

Podemos buscar en este enlace https://github.com/frida/frida/releases, nosotros utilizamos la última versión disponible (12.2.27).

Como en nuestro caso estamos utilizando un emulador basado en x86 tendremos que buscar el server de Frida que se corresponda a la arquitectura utilizada. Podemos buscar en este enlace https://github.com/frida/frida/releases, nosotros utilizamos la última versión disponible (12.2.27).

El siguiente paso será descomprimir y subir el fichero ejecutable del servidor al terminal Android, para esto realizamos lo siguiente mediante ADB

adb push .\frida-server-12.2.27-android-x86 /data/local/tmp/

Una vez subido le damos permisos de ejecución y lo lanzamos

chmod +x frida-server-12.2.27-android-x86
./frida-server-12.2.27-android-x86 &

Para comprobar el buen funcionamiento de Frida vamos a realizar una consulta para listar los procesos en ejecución

frida-ps.exe -U

Si nos aparece el listado de procesos, tenemos todo listo para ejecutar Frida.

 

Configuración BurpSuite

Para el caso de nuestro entorno de laboratorio hemos realizado lo siguiente para utilizar BurpSuite para capturar el tráfico.

  • Capturar el tráfico de todas las interfaces en las opciones del proxy
  • Lanzar el emulador de Android utilizando un proxy por defecto
    emulator.exe -avd AndroidEmu23 -netfast -http-proxy 192.168.1.100:8080
  • Importar el certificado del proxy de Burp dentro de los certificados confiables del terminal (importante cambiar la extensión de .der a .cer)

 

Realización del SSL Pinning Bypass

Para la realización del bypass utilizamos el siguiente script universal

https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/

frida-android-repinning.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/
*/

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…”)
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);

Para utilizar este script es necesario que enviemos el certificado confiable, que en este caso será el certificado de Burp que utilizamos anteriormente, a la ruta donde se encuentra el server de Frida. Es importante que establezcamos el nombre del certificado a cert-der.crt para el buen funcionamiento del script.

adb push .\cacert.cer /data/local/tmp/cert-der.crt

Para la realización de esta PoC utilizamos la app de Twitter. Si intentamos capturar la petición de login sin utilizar Frida veremos que nos lanza un error y que en Burp no se refleja ninguna petición.

Esto es debido a que la app de Twitter tiene SSLPinning y, cada vez que realiza una petición, comprueba que el certificado remoto se encuentra entre sus certificados confiables. Esto no ocurre debido a que se encuentra con que es Burp el que responde con su certificado y acaba mostrando ese error.

Vamos a poner en funcionamiento el bypass de Frida con el siguiente comando

frida -U --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f com.twitter.android --no-pause

Si no disponemos de salida a Internet podemos descargar el script, guardarlo con extensión .js y ejecutarlo de manera local

frida -U -l frida-android-repinning.js -f com.twitter.android --no-pause

Si volvemos a realizar el login podremos ver los resultados en nuestro Burp y que la app no muestra errores, además de poder capturar el contenido de la petición con nuestro Burp.

Referencias

http://omespino.com/tutorial-universal-android-ssl-pinning-in-10-minutes-with-frida/
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
https://labs.nettitude.com/tutorials/using-frida-to-bypass-snapchats-certificate-pinning/
https://www.exploit-db.com/papers/44145 https://github.com/dweinstein/awesome-frida

 

Espero que esta entrada os haya sido de interés, voy a sacar una serie de posts relacionados con Frida en el futuro 🙂

Matías Moreno Cárdenas

Publicado por: Matías Moreno Cárdenas

Analista de Seguridad IT y hacking ético / Desarrollador de Software Multiplataforma. Actualmente analista de seguridad informática y hacking ético en Grupo SIA

Deja un comentario