Anteriormente nos referíamos a cómo proteger la depuración remota de aplicaciones Java, y ceíamos cómo éstas pueden ser vulneradas si no se toman los recaudos debidos. Mencionábamos que el proceso de depuración en Java se lleva a cabo mediante el protocolo JDWP, Java Debug Wire Protocol, y que éste debe ser correctamente administrado, o de lo contrario un atacante podría dar el primer paso: conectar con la aplicación y acceder al sistema.

No sorprendentemente, este protocolo es también utilizado en procesos de depuración en aplicaciones Android. Si bien sujeto a algunos ajustes, conserva la mayor parte de las características esenciales de JDWP y es posible observar el mismo proceso de handshake en capturas de tráfico:handshake_android
El Dalvik Debug Monitor Server o DDMS extiende a JDWP, definiendo nuevos formatos de paquetes según los requisitos. Por cada aplicación de Android iniciada en modo debug, se instancia un hilo JDWP, el cual escucha un puerto en particular. Este hilo es luego utilizado por los depuradores para completar el proceso de comunicación. Cada máquina virtual en el dispositivo tiene una conexión con Android Debug Bridge (ADB). El DDMS se comunica con ADB para obtener una lista de las VMs, y luego usa ADB para interactuar con ellas.

El DDMS escucha diferentes puertos TCP para cada VM, por lo que es posible conectar “directamente” con éstas. Como conveniencia, escucha el puerto 8700, y redirige cualquier conexión a la máquina virtual actualmente seleccionada en la UI. Los desarrolladores enlazan comúnmente con este puerto mediante depuración remota asistida por el mismo IDE, o herramientas como IntelliJ, jdb, jswat, entre otras.

Recordemos que una aplicación es depurable si contiene el atributo android:debuggable="true" en el elemento <application> en el AndroidManifest.xml. Éstas son difíciles de encontrar, pero sin embargo, existen. Y en conjunción con un dispositivo que presente el modo de depuración vía TCP/IP habilitado, permiten a cualquier dispositivo en la misma red correctamente equipado iniciar el proceso de depuración para, por ejemplo, inyectar código de manera dinámica. Ya el mismo IDE advierte la peligrosidad de liberar aplicaciones en estas condiciones:

IDE_liberar_aplicaciones
Encontrando vulnerabilidades en la depuración remota en Android

A fin de una demostración práctica, creamos una pequeña aplicación depurable, instalada en un dispositivo que admite debugging remoto mediante TCP/IP. Esto último podemos lograrlo ejecutando los siguientes comandos en un smartphone rooteado:

smartphone_rooteado
La aplicación consta simplemente de una actividad principal, con un único botón que al ser presionado detonará el método posteriormente utilizado como breakpoint. Este método cambia el texto del botón por la cadena “Texto inicial”:

breakpoint
Un equipo con la herramienta adb instalada puede ahora conectarse al terminal como depurador. Para ello es necesario ejecutar este comando:

comando_depurar
Como paso siguiente, inspeccionaremos los procesos depurables en ejecución, para adquirir más información sobre ellos e identificar las aplicaciones vinculadas. En nuestro caso, podemos ver nuestra aplicación señuelo destacada en la figura:

aplicacion_señuelo
Una vez que el blanco ha sido identificado, comienza la etapa de depuración con la herramienta de preferencia. Esta vez, utilizaremos jdb. Debemos realizar port forwarding, para luego adherir el depurador a la aplicación, proceso que se ilustra a continuación:

port_forwarding
Inspeccionando las clases y métodos, podemos identificar aquel que responde al presionado del botón. Entonces, sobre el mismo fijamos un breakpoint. Luego, forzamos la ejecución del método interactuando con la GUI de la aplicación:

GUI_aplicacion
GUI
La inspección de las variables no sólo sirve al descubrimiento de posibles variables secretas almacenadas en el terminal, sino que además permite cambiar sus valores a voluntad como en este ejercicio, alterando la salida percibida por el usuario o modificando el flujo de control de la aplicación:

ejemplo_depuracion_android

Y ahora, ¿cómo nos protegemos ante estos posibles ataques?

En una primera instancia, es importante cerciorarnos de que nuestros dispositivos móviles poseen las opciones de depuración deshabilitadas, especialmente depuración sobre TCP/IP. Para ello, si nuestro smartphone se encuentra rooteado, podemos hacer uso del comando setprop antes visto y asignar un valor -1 a la propiedad service.adb.tcp.port.

Por otra parte, si queremos analizar un determinado apk para determinar si el mismo es depurable, podemos utilizar la herramienta aapt en el siguiente comando:

aapt dump badging {RUTA_APK}

Obtendremos una salida similar a la que se muestra en la siguiente imagen: si aparece la sentencia application-debuggable, entonces sabemos que la misma ha sido compilada en modo debug según lo indica la documentación de Android:

application-debuggeable
Como vimos, el proceso de depuración crea un punto de acceso a las aplicaciones que debe ser cuidado para evitar vulnerabilidades.