Introducción

El presente artículo se centra en el análisis exhaustivo de la capa de comunicación de una aplicación móvil Android de un reloj inteligente mediante la interceptación de tráfico de red y la manipulación de flujos de autenticación y datos. La relevancia de este análisis radica en la detección de vulnerabilidades críticas que, si bien pueden parecer fallos menores de implementación, representan riesgos operativos severos. Los vectores de ataque identificados abarcan desde fallos en la gestión de sesiones y credenciales (como la ausencia de mecanismos anti-fuerza bruta), hasta deficiencias en la lógica de negocio y la gestión de datos, permitiendo el acceso no autorizado a información de terceros.

Análisis

1. Gestión de credenciales y autenticación

El análisis se inicia mediante la apertura de la aplicación y la interceptación de las comunicaciones realizadas en red utilizando herramientas avanzadas como Frida y un proxy web. Se procede a evaluar tanto el proceso de creación de cuentas de usuario como el acceso anónimo.

POST /watch/users/login/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/json; charset=UTF-8
Host: backend.application.tld

{"account":"<EMAIL_ADDRESS>","password":"<MD5_ENCODED_PASSWORD>","type":2}

Se detectó una ausencia crítica de mecanismos de protección contra ataques de fuerza bruta en el proceso de inicio de sesión. El sistema permite un mínimo de cien intentos consecutivos sin aplicar ningún bloqueo o throttling, facilitando la adivinación de credenciales. El intercambio de contraseñas se realiza mediante el envío codificado con la función hash MD5. El uso de MD5 es considerado obsoleto y extremadamente inseguro para el almacenamiento de credenciales, ya que es susceptible a ataques de colisión y fuerza bruta con relativa facilidad.

El mecanismo de inicio de sesión no solo falla en la autenticación, sino que también permite la enumeración de usuarios. Al realizar la llamada de login, el servidor devuelve una respuesta estructurada que confirma explícitamente si el nombre de usuario (correo electrónico o UUID) existe o no en el sistema. Esta funcionalidad permite a un atacante mapear la base de datos de usuarios sin necesidad de conocer credenciales.

{  
    "code": 1009,  
    "data": "",  
    "message": "The user does not exist."  
}

2. Flujos de registro

El registro estándar solicita solo correo electrónico y contraseña. Se observa que, antes del registro, la aplicación solicita y genera un código de verificación enviado al correo electrónico del usuario.

POST /watch/users/blvcode/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/x-www-form-urlencoded
Host: backend.application.tld

language=es&smsType=1&title=Application&username=<EMAIL_ADDRESS>

A continuación se realiza la petición para verificar el registro. Es relevante notar que la aplicación no notifica al usuario mediante un correo secundario sobre la recepción o validación de este código.

POST /watch/users/register/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 83
Host: backend.application.tld

password=<PASSWORD>&device=2&vcode=<VERIFICATION_CODE>&username=<EMAIL_ADDRESS>

El proceso de registro anónimo es igualmente débil. Se genera un nombre de usuario mediante un código UUID aleatorio, y se asigna una contraseña prefijada (12345678). Para completar el registro, se simula un intento de login previo con el UUID generado para confirmar la inexistencia de la cuenta, lo cual se realiza mediante la siguiente ruta:

POST /watch/users/login/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/x-www-form-urlencoded
Host: backend.application.tld

password=<PASSWORD>&username=<RANDOM_UUID_CODE>

Para el registro anónimo, se utiliza un código de verificación prefijado en el código fuente (112233), eliminando el requisito de un mecanismo de One-Time Password (OTP) dinámico.

POST /watch/users/register/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 83
Host: backend.application.tld

password=12345678&device=2&vcode=112233&username=<RANDOM_UUID_CODE>

A continuación se inicia sesión automáticamente en la aplicación con un token recibido en el proceso de registro que es una cadena de 16 bytes codificada en Base64. En las siguientes peticiones la aplicación se autentica mediante la cabecera HTTP Access-Token con el valor <SESSION_ACCESS_TOKEN>.

3. Referencia directa insegura a objetos en datos de salud

Al analizar el comportamiento de la aplicación en la descarga y subida de datos de salud del usuario, se identificó una vulnerabilidad de referencia directa insegura a objetos (IDOR). La API utiliza un identificador numérico secuencial (userId) para referenciar los registros de datos de salud. Lo crítico es que, en las rutas de carga y descarga, no se realiza ninguna verificación de sesión o autorización sobre este campo.

Conocer previamente cualquier ID secuencial permite a un atacante obtener y modificar los datos de cualquier usuario en la base de datos. Dado que el ID es secuencial, es trivial realizar fuerza bruta sobre este parámetro para acceder a registros de otros usuarios.

POST /watch/data/heart/v1 HTTP/1.1
content-type: application/json;charset:utf-8
Access-Token: <SESSION_ACCESS_TOKEN>
User-Agent: okhttp/4.10.0
Host: backend.application.tld

[{"deviceMac":"<DEVICE_MAC_ADDRESS>","deviceModel":"<DEVICE_MODEL>","heartTimes":70,"hour":15,"rtime":<UNIX_TIMESTAMP>,"userId":"<SEQUENTIAL_USER_ID>","zone":"+1"}]

4. Recuperación de contraseña olvidada

Finalmente, se evaluó el mecanismo de recuperación de contraseña. El proceso implica: introducción de correo electrónico, solicitud del código de verificación, e ingreso del código y la nueva contraseña.

Se constata una irregularidad crítica en el manejo del código de verificación: aunque el servidor valida la validez del código, no existe ningún mecanismo de defensa contra ataques de fuerza bruta.

POST /watch/users/password/v1 HTTP/1.1
User-Agent: okhttp/4.10.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 73
Host: backend.application.tld
Connection: Keep-Alive
Accept-Encoding: gzip

password=<NEW_PASSWORD>&code=<VERIFICATION_CODE>&username=<EMAIL_ADDRESS>

Dado que el código es de seis cifras, esto otorga un espacio de búsqueda de un millón de combinaciones. Esto permite, con una dirección de correo objetivo, la posibilidad de cambiar la contraseña del usuario de forma no autorizada en un máximo de un millón de intentos, sin que se disponga de ninguna notificación de seguridad al usuario afectado.

Conclusión

Las vulnerabilidades detectadas no son meros defectos menores de código, sino fallos sistémicos en la implementación de la seguridad de la API y la gestión de identidades, que comprometen los tres pilares de la seguridad de la información: confidencialidad, integridad y disponibilidad, destacando el acceso a datos de salud cuyo grado de protección debe de ser máximo.