Lógica de autenticación del formulario de inicio de sesión

3

Estoy creando la acción del formulario de inicio de sesión y quiero asegurarme de que mi lógica sea sólida y lo más segura posible.

1.) Primero verifico si la dirección de correo electrónico proporcionada existe en la base de datos, si no, muestro un mensaje de error genérico Invalid e-mail address or password. y salgo. Aviso, el mensaje de error no especifica que el correo electrónico no existe.

2.) Luego verifico si failed_logins que está almacenado en la base de datos es mayor que 5. Si lo es, muestro un mensaje de error User has been locked out due to excessive invalid logins. y salgo. Observe que este mensaje se muestra si una cuenta de usuario está bloqueada, pero se proporcionó la contraseña incorrecta. Hice esto porque si una cuenta está bloqueada, no quiero que un posible pirata informático pueda determinar si proporcionó la contraseña correcta.

3.) Verifique la contraseña que compara el hash bcrypt en la base de datos con la contraseña provista. Si es incorrecto, muestre Invalid e-mail address or password. increment failed_logins en la base de datos y salga.

4.) Verifique la bandera activated en la base de datos. Si se activa, se establece en 0, luego se muestra un mensaje de error User is not activated. Aviso, deben proporcionar la contraseña correcta para ver este mensaje de error.

5.) Válido, establezca failed_logins de nuevo en 0 en la base de datos y configure las sesiones.

¿Hay algo en esta lógica que sea defectuoso o inseguro? Muchas gracias.

    
pregunta Justin 08.11.2012 - 03:21
fuente

4 respuestas

1

Algunos ataques para pensar:

Engaña a failed_logins borrando tu ID de sesión. Enumerar cuentas al tratar de bloquear las cuentas existentes. Haciendo cuentas administrativas cerrándolas con intentos de inicio de sesión fallidos. Enumerar los nombres de inicio de sesión con la función de contraseña olvidada o con el registro, o la referencia directa insegura de objetos. Falsificar su dirección IP mediante el suministro de un elemento de encabezado http x-forwarded-for .

Administración de sesiones interrumpidas: Sesión de sesión (CSRF), Caducidad de sesión, Fijación de sesión, Problemas con el dominio de cookie / Ámbito de la carpeta, Almacenamiento de ID de sesión en texto plano en la base de datos, Entropía insuficiente en ID de sesión. No establecer las banderas "seguro" y "HTTPOnly". Clickjacking. OWASP A9 ...

¿Me perdí algo?

YES

    
respondido por el rook 08.11.2012 - 05:23
fuente
1

Debes intercambiar los pasos 1 y 2 redondos. Debe mantener un registro separado de intentos de inicio de sesión por dirección de correo electrónico proporcionada, ya sea que el correo electrónico sea válido o no. Utilice las mismas reglas de sensibilidad a las mayúsculas y minúsculas que su base de datos de usuario para las direcciones de correo electrónico.

por ejemplo

[email protected], anypassword, = 1 failed_login
[email protected], anypassword, = 2 failed_logins
[email protected], invalidpassword = 1 failed_login
[email protected], invalidpw2 = 2 failed_logins

Puede restablecer el recuento de fail_login por dirección de correo electrónico después de un período de tiempo aleatorio (entonces un atacante no puede inferir que una dirección de correo electrónico no es válida ya que el mensaje de bloqueo persiste: esto "simula" un inicio de sesión válido para esa dirección de correo electrónico en los ojos del atacante).

Además, asegúrese de que el código para generar la presentación completa del mensaje de error esté configurado en el mismo fragmento de código. Si se muestra Invalid e-mail address or password , pero se genera en diferentes partes del código, puede haber diferencias sutiles en el HTML que el atacante podría detectar y utilizar para su ventaja. p.ej. si falló en el paso 1, podría generarse como <span>Invalid e-mail address or password</span> o si falló en el paso 3 podría ser <span id="message">Invalid e-mail address or password </span> ; no desea estas diferencias detectables, ya que el atacante puede inferir en qué etapa se encuentra su intento de inicio de sesión, por lo que es mejor usar el mismo código.

Además, podría introducir un tiempo para que su respuesta de inicio de sesión siempre lleve la misma cantidad de tiempo para volver al usuario. Puede configurar un temporizador al comienzo del proceso y verificar el temporizador al final (a cada paso que se haga). Luego, si todo el proceso es inferior a un tiempo establecido (por ejemplo, 1.5 s), el hilo se retrasa hasta que la cantidad total de tiempo haya pasado. Esto detendrá la detección "ciega" del paso de inicio de sesión debido al tiempo de respuesta del servidor.

    
respondido por el SilverlightFox 08.11.2012 - 13:05
fuente
1

Como desea ocultar si una dirección de correo electrónico determinada existe o no en el sistema, deberá hacer que los escenarios 1 y 3 sean más similares. @SilverlightFox sugiere agregar una pausa para que el tiempo que lleva el proceso de inicio de sesión sea siempre el mismo: es un paso en la buena dirección, pero no es suficiente. De hecho, cuando un hilo duerme , no utiliza la CPU, que es libre de realizar otras tareas. Un atacante laborioso administrará docenas o cientos de intentos de inicio de sesión en paralelo, y hará que su servidor rastree a la velocidad del caracol. En estas condiciones (carga muy pesada), cualquier intento de hacer hashing de una contraseña (con bcrypt) llevará mucho tiempo, es decir, un tiempo muy detectable .

Por lo tanto, para ocultar si una dirección de correo electrónico dada es un nombre de inicio de sesión válido o no, debe organizar siempre bcrypt. Además, no desea proporcionar la misma información a través del mensaje "cuenta bloqueada". Las cosas deberían ir así:

  1. Siempre registra el número de intentos por dirección de correo electrónico, ya sea que la dirección de correo electrónico exista o no en su sistema. Sé que esto es inconveniente (en términos de base de datos, necesitará otra tabla adicional). Si el recuento de intentos de una dirección de correo electrónico determinada supera los 5, rechaza el inicio de sesión.

  2. Usted echa un vistazo a la base de datos, para ver si existe la dirección de correo electrónico en el sistema y obtener el bcrypt salt. Si no lo hace, utiliza una sal extra fija. Entonces usted incondicionalmente calcula la parte bcrypt. Luego (y solo entonces), si la salida de bcrypt no coincide con el valor almacenado, o si se usó la sal extra fija, entonces se rechaza con "Correo electrónico o contraseña no válidos".

  3. Si el intento de inicio de sesión es exitoso, restableces el "conteo de intentos" para esa dirección de correo electrónico.

Ahora, la tabla adicional para realizar un seguimiento de los conteos de intentos puede ser inconveniente de muchas maneras, ya que puede crecer bastante rápido. Podrías hacer una variante en la que no tengas la tabla. En su lugar, puede mantener el recuento para cada usuario válido , pero luego debe rechazar los intentos de inicio de sesión con "Correo electrónico o contraseña no válidos" cuando el recuento está en 5, ya sea que bcrypt Salida coincidente o no. En otras palabras, puede darse el lujo de proporcionar al usuario cierta información sobre si su cuenta está bloqueada o no solo si esa información se calcula independientemente de si la cuenta existe o no (a través de la tabla adicional).

También se puede decir que bloquear cuentas para un servidor con inicios de sesión remotos es un poco severo, ya que permitiría a cualquiera bloquear la cuenta de cualquiera, por error o malicia. El bloqueo implica el desbloqueo manual, es decir, costos adicionales de asistencia técnica. Sugiero restablecer automáticamente todos los "intentos de conteo" cada dos horas: por lo tanto, el bloqueo es solo de dos horas, lo cual es suficiente para disuadir los ataques del diccionario y hacer que todo el sistema sea más robusto para las denegaciones de servicio.

    
respondido por el Thomas Pornin 13.11.2012 - 13:43
fuente
1

Confidencialidad. Parece que está intentando impedir que un atacante pruebe una dirección de correo electrónico en particular para ver si existe en su base de datos. Sin embargo, su esquema tiene un agujero: en realidad no logra esto.

Dada una dirección, digamos [email protected] , el atacante puede intentar iniciar sesión con esa dirección de correo electrónico 6 veces (usando una contraseña poco probable). Luego, el atacante puede intentar iniciar sesión una vez más.

  • Si el atacante recibe una respuesta Invalid e-mail address or password. , el atacante puede inferir que este correo electrónico no existe en su base de datos.

  • Si el atacante recibe un User has been locked out due to excessive invalid logins. , el atacante puede inferir que este correo electrónico existe en su base de datos.

Integridad. Su método para validar contraseñas parece correcto, y debería evitar que un atacante realice una búsqueda en el diccionario con la contraseña de un usuario en particular.

No evitará que un atacante realice una pequeña cantidad de intentos con una gran cantidad de contraseñas de usuarios. Supongamos que un atacante puede enumerar de alguna manera un conjunto de direcciones de correo electrónico que tienen un inicio de sesión con su servicio (tal vez por alguna búsqueda web inteligente, o explotando la brecha de confidencialidad anterior, o algo así; no sé si esto es realmente posible en su caso , pero vamos a explorar las consecuencias si es). Luego, un atacante puede recorrer todas esas cuentas y hacer 5 conjeturas sobre la contraseña de cada cuenta.

Investigaciones recientes ha encontrado que un atacante que puede hacer 10 intentos por cada cuenta Será capaz de comprometer alrededor del 1% de las cuentas. Extrapolando, podemos esperar que en su situación, un atacante pueda comprometer aproximadamente el 0,5% de las cuentas, haciendo 5 conjeturas en la contraseña de cada cuenta que el atacante conoce.

También puede hacer que este tipo de ataque de adivinanzas sea más difícil haciendo un seguimiento de la cantidad de intentos de inicio de sesión fallidos por dirección IP y bloqueando temporalmente los inicios de sesión de direcciones IP que tienen una gran cantidad de intentos de inicio de sesión fallidos. Sin embargo, esta no es una defensa perfecta (un atacante con una red de bots puede evitar esto fácilmente).

Disponibilidad. Sería fácil para un atacante bloquear a un usuario objetivo: todo lo que el atacante tiene que hacer es intentar iniciar sesión 6 veces con una contraseña poco probable, y ahora ese usuario no lo hará. ser capaz de iniciar sesión sin ponerse en contacto con su equipo de soporte. Esto podría ser un riesgo aceptable. La buena noticia es que si esto sucede con frecuencia, lo sabrá y podrá implementar defensas en ese momento.

Soluciones estándar. Preguntó si hay alguna solución estándar. Por lo que yo sé, no hay soluciones estándar. Sin embargo, en una vena relacionada, podría interesarle este artículo académico, que trata de evitar el uso de usuarios populares: si muchos otros usuarios han elegido la misma contraseña, los nuevos usuarios no pueden usarla. El documento tiene algunas estructuras de datos inteligentes para asegurarse de que esto no cree nuevos problemas de seguridad.

respondido por el D.W. 12.11.2012 - 03:58
fuente

Lea otras preguntas en las etiquetas