Bypass Flutter Protection — Hooking Verify Function
Simon says, listen to my proxy!
En este caso vamos a analizar un escenario en donde es posible hacer un bypass de la protección de proxy unaware de Flutter mediante un hook a la función de verificación de certificado.
Al ser un escenario real, muchos de los datos que identificarían al target, van a ser censurados o cambiados.
Introducción — Entendiendo el problema
Para interceptar el tráfico de una aplicación Android, generalmente basta con instalar el certificado de nuestro Burp Suite al dispositivo móvil y añadirlo al almacén de sistema. El problema con las aplicaciones creadas con Flutter es que ignoran cualquier tipo de certificado sea de usuario o de sistema. Otra complicación es que las aplicaciones en Flutter son proxy unaware, o sea que ignoran las configuraciones de proxy en el dispositivo. La solución entonces consiste en aplicar reglas de iptables para redirigir el tráfico y Frida para hacer un hook en la función de validación del certificado, en la librería libflutter.so para cambiar dicho valor siempre a true.
Proxying — Preparando el Lab
El emulador que vamos a estar utilizando Genymotion, en particular un Motorola Moto X con Android 11 — API 30 x86, rooteado.
Utilizando adb (Android Debug Bridge) vamos a configurar iptables para redirigir el tráfico a nuestro Burp Suite. Primero estableciendo un proxy HTTP en el localhost del dispositivo en el puerto 3333:
adb shell settings put global http_proxy localhost:3333
Nuevamente, como las aplicaciones en Flutter hacen caso omiso a esta configuración, usamos iptables para dirigir todo el tráfico HTTPS a localhost:
adb shell “iptables -t nat -F”
adb shell “iptables -t nat -A OUTPUT -p tcp — dport 443 -j DNAT — to-destination 127.0.0.1:3333
adb shell “iptables -t nat -A POSTROUTING -p tcp — dport 443 -j MASQUERADE”
Ahora esteblecemos un reverse tunnel con adb para hacer un forward del tráfico del dispositivo en el puerto 3333 a nuestro Burp escuchando en el 8080:
adb reverse tcp:3333 tcp:8080
Finalmente, en el Burp necesitamos forzar el tráfico al puerto 443, además de soportar el invisible proxying. Esta configuración la encontramos en Proxy > Proxy Settings > Edit > Request handling:
Hooking — Firing up Frida
Esta puede ser la parte más complicada de explicar y entender, pero, en resumidas cuentas, sería necesario analizar la librería libflutter.so de la aplicación para hacer un hook de la función ssl_verify_peer_cert. Para esto tendríamos que investigar en qué región en hexadecimal se compiló dicha función, por ejemplo, podría ser en “0x6ccf0c” para hacer el hook.
Al tener control de esta función, cada vez que quiera validar el certificado, se forzará la respuesta siempre a valor 1, o true.
En este caso no sería necesario todo el proceso de ingeniería inversa porque ya tenemos un script de Frida automatizado para ello:
Por lo tanto sólo faltaría iniciar Frida, descargando la versión correcta de server para nuestro dispositivo en https://github.com/frida/frida/releases y moviéndolo dentro:
adb push .\frida-server-16.0.8-android-x86_64 /data/local/tmp/frida-server
Mediante adb podemos cambiarle los permisos y ejecutarlo:
adb shell “chmod 755 /data/local/tmp/frida-server”
adb shell “/data/local/tmp/frida-server &”
Una vez con el server en escucha, buscamos las aplicaciones en ejecución en el dispositivo para anotar la que buscamos:
frida-ps -Ua
Ya con el proceso identificado, iniciamos el hook:
frida -U -f com.demo.app -l C:\[script location]\disable-flutter-tls.js
Cómo vemos, en este caso la función fue compilada en “0x41e3db”. Ahora sí! Finalmente podemos ver el tráfico interceptado en nuestro Burp Suite y continuar con nuestro pentest :D
Este post fue posible gracias a otro de Adan Álvarez, kudos! (https://www.donttouchmy.net/pentest/trafico-https-de-app-flutter-con-burp-usando-genymotion-paas/)
>>>print(“h4ppy_h4ck1ng”)
>>>exit()