Fallas Lógicas de Negocio, Seguridad Web

Bypass en flujos de registro: una falla lógica común en aplicaciones web

Cuando la interfaz bloquea el registro, pero la API sigue permitiendo crear usuarios.

Resumen

Durante el pentest, luego de la etapa de reconocimiento, se descubrió un endpoint dentro de un subdominio. Dicho registro “no funcionaba” para un visitante, pero los controles estaban implementados en el frontend. Al revisar el comportamiento del cliente web se infirieron los campos requeridos (por ejemplo, un parámetro tipo type) según errores encontrados, aunque dichos parametros no eran explicitamente requeridos en el registro encontrado, luego se logró completar el alta. La cuenta quedó con permisos bajos, pero descubrimos post autenticación que la aplicación contaba con menús ocultos pero solo a nivel de front, es decir, aparecían como hidden. Esto sumado a que no había validación correcta en backend, permitió realizar ciertas acciones como usuario con altos privilegios.

Qué falló

Se confiaba en restricciones del cliente (UI/JS) para impedir altas, y luego se repetía el patrón dentro de la aplicación: la autorización no se reforzaba de forma consistente del lado del servidor.

Paso a paso (alto nivel)

  • Recon: fuzzing/enumeración de subdominios para ampliar superficie de ataque.
  • Descubrimiento: fuzzing/enumeración de directorios sobre los subdominios encontrados.
  • Hallazgo: identificación de una ruta/feature de register en uno de los subdominios.
  • Intento inicial: el registro no permitía crear cuentas “desde afuera” (consistente con que el alta era interna para empleados).
  • Análisis del flujo: revisión del frontend (formularios, requests, lógica JS, parámetros enviados).
  • Inferencia de campos: se detectaron campos requeridos “no obvios” para un usuario final (por ejemplo type) y se reconstruyó una request válida.
  • Resultado: creación exitosa de una cuenta con permisos low.
  • Post-auth: navegación del portal y acceso a menús, secciones, acciones y datos que no deberían estar disponibles para ese perfil.
  • Causa del post-auth: controles de autorización inconsistentes, con decisiones tomadas del lado cliente o sin verificación robusta en backend.

Nota

El objetivo de este “paso a paso” es describir la secuencia de la evaluación. No se incluyen endpoints, valores reales ni detalles operativos explotables.

El detalle del bypass: campos “internos” adivinables

El punto clave fue que el flujo de alta dependía de parámetros que el usuario no veía en el formulario, pero que el backend requería y podían ser enviados al manipular un request (por ejemplo type). Al observar el comportamiento del cliente web (campos ocultos, requests y payloads), se pudo inferir qué parámetros eran obligatorios y construir una solicitud completa. Cuando el backend acepta esos valores sin validarlos contra reglas de negocio, el “bloqueo” del registro termina siendo solo del lado UI.

// Ejemplo:
POST /registro
{
  "email": "usuario@ejemplo.com",
  "password": "****",
  "type": "..."
}

Lectura defensiva

Si un parámetro define flujo/rol/tipo, el backend debe decidirlo y validarlo. No debería aceptarse como “llave” enviada por el cliente.

Acceso inicial y escalamiento de privilegios

Luego, obtuvimos acceso a la aplicación. Aunque no parecía tener muchas funcionalidades, al navegar la página y leer el codigo fuente, descubrimos que muchos campos figuraban con el tag HTML «hidden», así que procedimos a cambiar el tag y acceder a cada uno de ellos. Además, claro está, de iniciar una nueva etapa de reconocimiento, tal como al inicio. De esta manera logramos acceder a funcionalidades no destinadas a un usuario con privilegios como el nuestro.

Impacto

  • Creación de cuentas en una aplicación que no tenía alta pública.
  • Acceso post-login a menús/secciones no esperadas para un perfil con bajos privilegios.
  • Riesgo de exposición de funcionalidades internas, datos sensibles y ejecución de acciones no deseadas.

Recomendaciones breves

  • Registro: validación final server-side de elegibilidad y estado (no confiar en UI).
  • Parámetros internos: tratarlos como no confiables; validar/derivar en servidor.
  • Autorización: reforzar la lógica en backend para cada recurso/acción (no solo esconder menús).
  • Testing: incluir pruebas específicas de “salteo de flujo” (skip steps) y control de acceso post-auth.

Aclaración: Caso real anonimizado. Sin datos del cliente ni detalles sensibles.