La semana pasada, nuestro equipo de SecOps detectó un pico inusual de tráfico en la API de pagos proveniente de dispositivos con firmas legítimas pero comportamientos anómalos. No era un error de código; alguien estaba realizando ingeniería inversa activa. A pesar de usar HTTPS, los atacantes interceptaban el tráfico mediante un proxy MITM y un script de Frida para evitar nuestras validaciones en tiempo de ejecución. En el panorama actual de la Seguridad móvil, confiar únicamente en el cifrado TLS estándar es negligencia. Aquí documento cómo cerramos esa brecha.
Análisis de la Vulnerabilidad: Por qué HTTPS falla ante Frida
El problema fundamental no es el protocolo TLS, sino la cadena de confianza. En un ataque MITM clásico, el atacante instala un certificado CA personalizado en el almacén de confianza del dispositivo (User Certificate Store). Herramientas como Charles Proxy o Burp Suite dependen de esto. Sin embargo, cuando endurecemos la aplicación para que solo confíe en el System Store, los atacantes recurren a la inyección dinámica.
Frida permite a un atacante engancharse (hook) a las funciones nativas de verificación de certificados como SSLContext en Java o boringssl en nivel nativo, forzando a la aplicación a aceptar cualquier certificado como válido. Esto deja expuesta la lógica de negocio tanto en Seguridad Android como en entornos iOS.
Para mitigar esto, necesitamos una defensa en profundidad: SSL Pinning forzado y detección activa del agente Frida.
La Solución: Pinning Estricto y Defensa Nativa
A continuación, presento la implementación técnica que desplegamos para resolver el incidente. Utilizamos OkHttp para el pinning en Android debido a su robustez frente a la configuración XML estándar de Android Network Security, que es más fácil de eludir.
1. Implementación de SSL Pinning (Android)
Este código fuerza la verificación del hash SHA-256 de la clave pública del certificado. Si el hash no coincide (como sucede con un certificado de Charles Proxy), la conexión se aborta inmediatamente.
// Configuración de OkHttp para SSL Pinning estricto
// Reemplace los hashes con los de su certificado real (Subject Public Key Info)
String hostname = "api.tusempresa.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") // Backup Key
.add(hostname, "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // Primary Key
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
// Nota: Siempre incluya al menos un hash de respaldo (Backup Key)
// para evitar denegación de servicio si su certificado principal expira o rota.
2. Estrategia de Defensa Frida (Nativo/C)
El SSL Pinning por sí solo es vulnerable si un script de Frida hace un hook a la función checkServerTrusted y la anula. Para una verdadera Defensa Frida, debemos descender al nivel nativo (NDK en Android) y detectar la presencia del servidor de Frida.
El siguiente código en C busca los puertos predeterminados de frida-server y verifica mapas de memoria sospechosos.
// native-lib.c
#include <jni.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
// Función para detectar si el puerto por defecto de Frida (27042) está abierto
int check_frida_port() {
struct sockaddr_in sa;
int sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(27042); // Puerto por defecto de frida-server
inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr);
// Si podemos conectar, algo está escuchando en ese puerto (probablemente Frida)
int res = connect(sock, (struct sockaddr *)&sa, sizeof(sa));
close(sock);
if (res == 0) {
return 1; // Detectado
}
return 0;
}
JNIEXPORT jboolean JNICALL
Java_com_tuapp_seguridad_AntiDebug_detectarFrida(JNIEnv *env, jobject thiz) {
if (check_frida_port()) {
return JNI_TRUE;
}
// Agregar más comprobaciones aquí (leer /proc/self/maps, buscar "frida-agent")
return JNI_FALSE;
}
Validación de la Eficacia
Implementar estas medidas no es una "bala de plata", pero eleva drásticamente el costo del ataque. A continuación, comparamos el estado antes y después de aplicar el parche en producción.
| Vector de Ataque | Antes (Solo HTTPS) | Después (Pinning + Anti-Frida) |
|---|---|---|
| Proxy MITM (Charles/Burp) | Vulnerable (Tráfico descifrado) | Bloqueado (Conexión rechazada por hash mismatch) |
| SSL Unpinning (Script Básico) | Vulnerable | Mitigado (Requiere bypass de capa nativa) |
| Inyección Frida Runtime | Permitido | Detectado (App se cierra o reporta al backend) |
Conclusión
La seguridad en aplicaciones móviles es una carrera armamentista continua. Al implementar SSL Pinning con bibliotecas robustas como OkHttp y combinarlo con defensas nativas contra herramientas de instrumentación, protegemos no solo la integridad de los datos, sino la confianza del usuario. No espere a ver logs extraños en su backend; audite su implementación de TLS hoy mismo y asuma que el dispositivo cliente está comprometido por defecto.
Ver Guía OWASP MASVS
Post a Comment