Seguridad

Identification and authentication failures

¿Identificación, autenticación o autorización?

Primero, debemos entender la diferencia entre identificación y autenticación:

  • Identificación: Es el proceso donde se proporciona una identidad; un usuario o sistema indica quién es. 
  • Autenticación: Es el proceso de verificar una identidad. Cuando un usuario o sistema se identifica, indica quién es; cuando se autentica, se comprueba que sea quien dice ser. 

Aunque la mayoría de los fallos más conocidos son de autenticación, ya que ahí se realizan los controles de seguridad para verificar la identidad de los usuarios, también existen fallos en el proceso de identificación que pueden afectar a la seguridad de la información. Algunos ejemplos son:

  • Identificación incorrecta o no reconocida: Si un usuario introduce un nombre de usuario o ID no registrado en el sistema, el proceso de identificación falla porque no se encuentra ninguna identidad asociada a esa entrada. 
  • Identidad duplicada: En algunos sistemas, pueden existir dos cuentas con nombres de usuario similares o ID muy parecidos, lo que genera confusión al intentar asociar a qué usuario se refiere la identificación. 

Por otra parte, es crucial entender la diferencia entre autenticación y autorización, que, aunque suenan similar, son procesos distintos. Mientras la autenticación, como hemos explicado, verifica la identidad de un usuario o sistema, la autorización determina si ese usuario o sistema tiene permiso para realizar o acceder a determinada acción o recurso.

Factores de autenticación

Existen tres tipos principales de factores de autenticación, basados en principios simples: algo que el usuario sabe, algo que el usuario tiene y algo que el usuario es.

  • Algo que el usuario sabe: por ejemplo, una contraseña o la respuesta a una pregunta de seguridad. 
  • Algo que el usuario tiene: como un objeto físico o un token de seguridad. 
  • Algo que el usuario es: como un dato biométrico (huella dactilar) o patrones de comportamiento. 

Aunque las contraseñas siguen siendo el mecanismo de autenticación más común, cada sistema puede requerir diferentes tipos de factores para verificar la identidad del usuario. Hoy en día, existen múltiples mecanismos: desde aquellos basados únicamente en datos biométricos (como el desbloqueo de smartphones) hasta los que utilizan hardware específico (como dispositivos extraíbles). Además, es cada vez más frecuente el uso de autenticación multifactorial, combinando, por ejemplo, contraseñas con tokens de seguridad.

Este panorama diverso de mecanismos de autenticación ofrece mayor flexibilidad y mejora la seguridad general de los sistemas. Sin embargo, también introduce nuevas complejidades y potenciales puntos débiles que los atacantes podrían explotar.

A continuación, analizaremos los distintos tipos de vulnerabilidades relacionadas con el proceso de autenticación, agrupándolas según el mecanismo afectado. Nos centraremos en estas vulnerabilidades ya que representan la mayoría de los fallos de seguridad en este ámbito.

Autenticación basada en contraseña

Los sistemas que utilizan únicamente usuario y contraseña como método de autenticación confían plenamente en la contraseña como prueba de identidad del usuario. Esto implica que un atacante que obtenga las credenciales de un usuario podría comprometer completamente el proceso de autenticación. Existen diversos tipos de ataques para vulnerar este mecanismo:

Fuerza bruta

Los ataques de fuerza bruta son un proceso de prueba y error donde el atacante introduce constantemente distintas credenciales —de manera aleatoria, siguiendo reglas o utilizando diccionarios de palabras— con el fin de descubrir las credenciales de un usuario legítimo.

Antes de intentar descubrir la contraseña, si no se conoce ningún nombre de usuario, es necesario realizar una enumeración de usuarios. Existen varios métodos para identificar nombres de usuarios válidos en una aplicación web.

El primero se basa en la respuesta del servidor. Al introducir un usuario registrado en la aplicación, recibimos una respuesta distinta a la que obtenemos al introducir un usuario inexistente. Para automatizar este proceso, podemos utilizar herramientas como el Intruder de BurpSuite, que permite realizar ataques de fuerza bruta a parámetros en una petición web utilizando diccionarios de palabras o reglas para generar secuencias de caracteres y números. En el siguiente ejemplo, observamos que una de las palabras introducidas devuelve una respuesta de tamaño distinto al resto:

Verificamos en la respuesta de esta petición que la plataforma indica que la contraseña no es válida, a diferencia del resto de respuestas que señalan que el usuario introducido no es válido:


No siempre es algo tan obvio; a veces debemos fijarnos en fallos sutiles del propio programa. En el siguiente caso, observamos una situación similar. Aunque todas las respuestas tienen distinto tamaño e indican que el usuario o la contraseña no son válidos, existe un pequeño fallo ortográfico en la programación de la respuesta. Este error provoca que, al introducir un usuario existente, se produzca una ligera variación en la respuesta:
  • Respuesta correcta: 

  • Respuesta incorrecta: 

Otro método, cuando la respuesta es siempre la misma, es utilizar el tiempo de respuesta como indicador. Si introducimos una contraseña muy larga, y el servidor solo la procesa al acertar el usuario, es posible que tarde más tiempo al tratar de procesar una cadena de caracteres tan extensa. En este ejemplo, probamos con distintos usuarios utilizando siempre una contraseña muy larga:

Existen muchas más técnicas de enumeración de usuarios. Si estás interesado en conocerlas, puedes visitar nuestra publicación sobre la vulnerabilidad de «Insecure Design» de OWASP.

Evasión de bloqueos por IP

Es posible encontrarnos con restricciones de inicio de sesión. El bloqueo más común es el de IP, donde el servidor bloquea temporalmente los intentos de inicio de sesión desde una dirección IP específica. Sin embargo, existen métodos para evadir este bloqueo. Por ejemplo, el uso de cabeceras como X-Forwarded-For, que, si es procesada por el servidor, puede llevar a una evasión del bloqueo de IP.

En otros casos, el bloqueo puede ocurrir cada cierto número de intentos, pero se reinicia una vez que se inicia sesión correctamente. Por ejemplo, si detectamos que la IP se bloquea cada 3 intentos, podemos usar un diccionario de credenciales e intercalar las credenciales de un usuario legítimo (necesitamos poseer credenciales de algún usuario) cada 2 entradas del diccionario. Con este método, podemos evitar el bloqueo y probar todas las entradas de nuestro diccionario.
También existen casos donde la enumeración o evasión del esquema de autenticación se puede realizar con una única petición HTTP, evadiendo así cualquier bloqueo por repetición de intentos de inicio de sesión. Por ejemplo, al enviar un JSON para iniciar sesión, si enviamos un array de contraseñas en lugar de un valor único, el servidor podría procesar correctamente este JSON y permitirnos iniciar sesión sin conocer las credenciales de usuario correctas.

Evasión del bloqueo de cuenta de usuario

El bloqueo de cuenta es otro mecanismo de seguridad. A diferencia del bloqueo por IP, este método bloquea la cuenta después de múltiples intentos fallidos de inicio de sesión. Sin embargo, si el sistema solo bloquea cuentas existentes, esto puede llevar inadvertidamente a una enumeración de usuarios. Por ejemplo, al intentar iniciar sesión repetidamente con diferentes nombres de usuario, notamos que una cuenta en particular se bloquea después del quinto intento fallido:

De este modo, logramos una enumeración de usuario en el panel de inicio de sesión de la aplicación web.

Autenticación de acceso básica

Aunque este método es muy antiguo, aún es posible encontrar servidores que utilicen este sistema vulnerable. Este mecanismo de autenticación consiste en concatenar el nombre de usuario y la contraseña, codificarlos en Base64, e introducirlos en la cabecera Authorization  en cada petición:

Este método es particularmente peligroso. A menos que la página web implemente HSTS, un atacante que realice un ataque de hombre en el medio podría interceptar esta cabecera. Con solo decodificarla, obtendría las credenciales del usuario.

Autenticación de factor múltiple

Los métodos de autenticación basados únicamente en contraseña depositan toda la seguridad en un solo parámetro: algo que el usuario sabe.

En contraste, la autenticación multifactorial introduce al menos un factor adicional. Un ejemplo común es la autenticación de dos factores (2FA), que requiere algo que el usuario sabe (una contraseña) y algo que tiene (como un código de un solo uso enviado por correo electrónico). Sin embargo, existen otras combinaciones, como el uso de huellas dactilares —algo que el usuario es— o aplicaciones de autenticación como Microsoft Authenticator, una app móvil que sustituye al código enviado por email.


Evasión del doble factor de autenticación

El caso más simple ocurre cuando el sistema considera al usuario autenticado tras introducir solo el primer factor, a pesar de solicitar un segundo. Por ejemplo, si conocemos la contraseña de un usuario y tenemos información sobre directorios o recursos reservados para usuarios autenticados, podríamos acceder a estos directamente sin proporcionar el token de seguridad solicitado. Esto evidencia una implementación deficiente del segundo factor de autenticación, ya que el sistema debería considerar autenticados únicamente a los usuarios que hayan completado todo el proceso.

Movimiento lateral por fallo de implementación

Similar al caso anterior, aquí observamos un problema en la verificación de que todos los pasos del proceso han sido realizados por el usuario que intenta acceder. Aunque puede parecer confuso, el siguiente ejemplo lo ilustra claramente.

Consideremos una web con autenticación de dos factores (2FA). Tras introducir usuario y contraseña, la aplicación solicita un token de seguridad para confirmar la identidad. Se realiza una petición GET a /login2 para que el servidor envíe el token al email del usuario. El servidor envía este token al usuario especificado en la cabecera Cookie de la petición:

De este modo, si reemplazamos nuestro nombre de usuario por el de la víctima, el servidor enviará el token de acceso al correo electrónico del usuario víctima:

Una vez este token llega al email de la víctima, el atacante puede comenzar el inicio de sesión con sus propias credenciales de usuario y pasar al proceso de introducir el token. A la hora de introducir el token, si cambia de nuevo esta cabecera Cookie para introducir el nombre de usuario víctima y realiza fuerza bruta sobre el token de seguridad, podrá descubrir el token de seguridad enviado al email y acceder con este al usuario víctima:


En este caso, el servidor solo verifica el segundo paso del proceso de autenticación, es decir, el token de seguridad. Si el token es válido y coincide con el enviado al usuario especificado en la cabecera Cookie, el servidor concede el acceso. Sin embargo, no valida que las credenciales proporcionadas en el primer paso de la autenticación (como el nombre de usuario y la contraseña) correspondan al usuario al que se está intentando acceder.

Vulnerabilidades en otros mecanismos de autenticación

Las vulnerabilidades asociadas al proceso de autenticación no se limitan únicamente al inicio de sesión. También pueden encontrarse en otros procedimientos críticos, como el cambio de contraseña, la actualización de la dirección de correo electrónico o la gestión de la persistencia de la sesión, como veremos a continuación.

Opción de “Mantenme autenticado”

En muchas páginas web, al iniciar sesión, se ofrece la opción de mantener la sesión activa incluso si cerramos y volvemos a abrir el navegador. Esta funcionalidad se implementa mediante una cookie persistente, similar a una cookie de sesión, pero con una duración más prolongada (al menos durante un tiempo determinado). Aunque esta práctica es muy común, la seguridad de la aplicación puede verse comprometida dependiendo de cómo esté diseñado y gestionado este token.

En el siguiente ejemplo, al seleccionar la opción de mantener la sesión iniciada e iniciar sesión, observamos la presencia de las siguientes cookies:


La primera cookie corresponde a la sesión activa, mientras que la segunda es la cookie persistente mencionada anteriormente. Este token debería ser accesible únicamente para el usuario que ha iniciado sesión. Sin embargo, al analizarlo, hemos observado que es relativamente predecible, ya que está codificado en Base64 y contiene el nombre de usuario seguido del hash MD5 de su contraseña:


Conociendo la estructura del token, es posible intentar un ataque de fuerza bruta para generar un token válido y acceder a la cuenta del usuario. Para ello, utilizaremos Intruder de BurpSuite para hacer un fuzzing del parámetro correspondiente a la cookie persistente. El primer paso será convertir todas las contraseñas en sus respectivos hashes MD5:

Una vez creada la lista de hashes MD5, la utilizaremos como diccionario para nuestro ataque. Sin embargo, antes de ello, es necesario realizar un post-procesamiento del diccionario: agregaremos como prefijo el nombre de usuario de la víctima seguido de :, y luego convertiremos toda la cadena a Base64. Posteriormente, ejecutamos el ataque con Intruder, lo que nos permitirá obtener una respuesta exitosa al acceder al perfil de la víctima utilizando una de las cookies persistentes generadas.

Robo de cookie a través de XSS

Es posible que el servidor nos bloquee si realizamos demasiadas solicitudes al probar distintos tokens, pero existen otros métodos para eludir esta restricción. En lugar de probar múltiples cookies, podríamos intentar robar la cookie de sesión de un usuario. Si el token sigue un esquema como usuario:hash[contraseña], tal como en el caso anterior, podemos intentar descifrar el hash mediante fuerza bruta utilizando herramientas como hashcat. Pero ¿cómo podemos obtener la cookie de un usuario? Esto se puede lograr a través de un ataque XSS, como se detalla en el siguiente ejemplo.

La sección de comentarios de uno de los blogs resulta ser vulnerable a una inyección de código JavaScript. Esta página es accesible para otros usuarios, por lo que al inyectar código malicioso, nuestra víctima podría acceder a la sección de comentarios y ejecutar el código JavaScript sin darse cuenta. Para robar la cookie de sesión, primero configuramos un servidor que espere recibir peticiones, y luego inyectamos el siguiente código en los comentarios:

De esta manera, la víctima, al tratar de cargar ese objeto i, hará una petición a nuestro servidor insertando sus cookies de sesión en dicha petición. Acto seguido, recibiremos esta información en nuestro servidor, como observamos en la siguiente imagen:

Observamos de nuevo que se trata de una cadena de texto codificada en Base64 con el siguiente formato:

Como el servidor nos bloquea al hacer muchas peticiones, podemos tratar de crackear este hash utilizando hashcat utilizando un diccionario como rockyou.txt:


Como observamos en la imagen, conseguimos crackear el hash y obtener la contraseña de la víctima.

Error en cambio de contraseña

Es posible identificar fallas en la lógica del proceso de cambio de contraseña, especialmente cuando un usuario olvida su contraseña y solicita un cambio a través del correo electrónico. En este caso, se envía un enlace al correo asociado al usuario que ha olvidado su contraseña, permitiéndole cambiarla por una nueva. Sin embargo, la solicitud que se realiza al hacer clic en el enlace incluye en el cuerpo los siguientes parámetros:

Como vemos, hay un parámetro indicando el usuario, y este es modificable por el usuario. Si en lugar de nuestro usuario, escribimos el nombre de usuario de la víctima logramos cambiar la contraseña de la víctima sin conocer su contraseña actual:




Envenenamiento de cambio de contraseña

Para comprender esta vulnerabilidad, es fundamental explicar primero el funcionamiento del proceso de cambio de contraseña. Generalmente, cuando un usuario olvida su contraseña, el servidor envía un enlace al correo electrónico asociado que redirige a una página para restablecerla. Dado que el usuario no puede acceder a su cuenta, no puede utilizar un token de sesión para verificar su identidad. Por esta razón, el servidor a menudo genera un token de un solo uso e incrusta este token en el enlace de redirección a la página de cambio de contraseña. La seguridad de este token se basa en que solo el usuario que tiene acceso a su correo electrónico puede acceder al enlace y, por ende, al token, y que, una vez utilizado, el token pierde su validez.

Sin embargo, existe una vulnerabilidad que puede comprometer este sistema. Al crear el enlace de cambio de contraseña, el servidor debe incluir en la URL tanto el host como el parámetro del token:

El host debería ser siempre el mismo, correspondiente a la página web legítima. Sin embargo, en ciertos casos, el servidor determina el host de la URL en función del valor de la cabecera Host de la solicitud realizada cuando el cliente hace clic en «enviar email», y esta cabecera puede ser manipulada por un atacante. De este modo, un actor malicioso puede engañar al servidor para que envíe un correo electrónico con un enlace malicioso a la víctima.

Para llevar a cabo este ataque, el atacante debe hacer clic en el botón de «contraseña olvidada» e ingresar el nombre de usuario de la víctima en lugar del propio. Luego, utilizando una herramienta de proxy como BurpSuite, intercepta la solicitud y modifica la cabecera Host, reemplazando el host del servidor por la URL de un servidor que esté bajo su control:

De esta forma, el servidor enviará al correo electrónico de la víctima un enlace para cambiar la contraseña, incluyendo un token temporal. Sin embargo, el host de dicho enlace pertenecerá al atacante. Si la víctima hace clic en este enlace, enviará una solicitud al servidor del atacante, que interceptará la petición y capturará el token temporal. De este modo, el atacante podrá cambiar la contraseña de la víctima y apoderarse de su cuenta de usuario.

Es posible encontrar servidores que admiten cabeceras no estándar y, en este contexto, en lugar de utilizar la cabecera Host para generar el enlace, el servidor podría emplear cabeceras como X-Forwarded-Host:

Cómo prevenir ataques de autenticación

Proteger los mecanismos de autenticación es fundamental para evitar vulnerabilidades que puedan comprometer un sitio web y los datos de los usuarios. A continuación, se destacan las medidas más significantes:

  1. Cuidado con las credenciales: Nunca enviar datos de inicio de sesión a través de conexiones no cifradas. Implementar HTTPS y redirigir automáticamente las solicitudes HTTP. Auditar el sitio para evitar la exposición de nombres de usuario o correos electrónicos. 
  2. No depender de los usuarios: Los usuarios suelen evitar políticas estrictas de seguridad. En lugar de aplicar políticas tradicionales de contraseñas, es más eficaz utilizar verificadores de contraseñas, como la biblioteca zxcvbn, que brindan retroalimentación en tiempo real sobre la fortaleza de las contraseñas. 
  3. Prevenir la enumeración de nombres de usuario: Evitar dar pistas sobre si un usuario existe en el sistema mediante mensajes de error genéricos, con tiempos de respuesta y códigos HTTP idénticos. 
  4. Protección contra ataques de fuerza bruta: Implementar límites en el número de intentos de inicio de sesión por dirección IP y utilizar CAPTCHA después de varios intentos fallidos. Esto dificulta que los atacantes realicen ataques de fuerza bruta de manera eficiente. 
  5. Verificación de lógica: Auditar exhaustivamente la lógica de autenticación para asegurarse de que no haya fallos o posibles bypasses que puedan ser explotados. 
  6. Atención a funcionalidades adicionales: Funciones como el restablecimiento de contraseñas también son vulnerables, por lo que deben ser tan seguras como el inicio de sesión principal. 
  7. Autenticación multifactor (2FA): Implementar 2FA usando aplicaciones o dispositivos dedicados es más seguro que métodos como el envío de códigos por SMS o correo. Auditar la lógica del 2FA para evitar que sea eludido. 


Egoitz San Martín, analista de ciberseguridad en el Grupo Zerolynx

Powered by WPeMatico

Gustavo Genez

Informático de corazón y apasionado por la tecnología. La misión de este blog es llegar a los usuarios y profesionales con información y trucos acerca de la Seguridad Informática.