Autenticación de usuarios a aplicaciones web sin enviar una contraseña. ¿Alguien puede sugerir mejoras?

1

Me ha interesado implementar un método de autenticación para una aplicación web que se ejecuta en navegadores modernos, sin tener que enviar la contraseña por cable.

¿Puede alguien sugerir mejoras o incluso decirme si me estoy yendo mal?

La autenticación se realiza a través de una conexión HTTP no segura mediante AJAX.

Mi comprensión actual de una implementación de protocolo de autenticación

El servidor tiene una contraseña de usuario que se ocultó utilizando bcrypt y se almacenó durante el registro.

El usuario ingresa id y password . Se envía un XMLHttpRequest al servidor para comenzar la autenticación, X-R1 es un entero aleatorio creado en el cliente.

GET /auth/{id} HTTP/1.1
X-R1: 123412341234
  1. El servidor obtiene valores.

    • ServerPassword : los usuarios no pueden codificar la contraseña de la base de datos de contraseñas

    • X-Salt : extrae la sal de ServerPassword

    • X-R1 - del cliente en el encabezado de la solicitud

    • X-R2 - entero generado aleatoriamente en el servidor.

  2. El servidor crea valores

    • X-Session - clave de sesión, concatenando X-R1 + X-R2 + id , de esta manera una forma hash esta cadena

    • Verifier - secreto compartido, concatenando X-R1 + X-R2 + ServerPassword y luego una forma de hashing de esta cadena.

    • Guarda estos valores en un almacén de sesión.

Respuesta del servidor.

HTTP/1.1 202 ACCEPTED
X-R2: 432143214321
X-Salt: $2a$10$rBV2JDeWW3.vKyeQcM8fFO
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
  1. El cliente obtiene valores

    • X-R1 : el mismo valor desde antes de enviar la solicitud.

    • ClientPassword : texto sin formato, lo que ingresó el usuario.

    • X-R2 - desde el encabezado del servidor enviado

    • X-Salt - desde el encabezado del servidor enviado.

  2. El cliente crea valores

    • HashedPassword : se creó usando una implementación de JavaScript de bcrypt usando ClientPassword y X-Salt

    • Verifier - Concatenando X-R1 + X-R2 + HashedPassword y luego una forma de hash de este valor. El cliente utiliza una implementación de JavaScript de bcrypt para codificar la contraseña que el usuario ingresó con la cadena X-Salt .

Ahora, tanto el cliente como el servidor creen que tienen el mismo verificador, por lo que para confirmar este cliente envía una solicitud adicional, pero esta vez se combinan los encabezados y el cuerpo de la solicitud con el verificador y luego se agrega 'X-Auth' a los encabezados con hash resultante.

POST /auth/{id} HTTP/1.1
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
X-Auth: ad801198a9fab4e4ef79eb97624a4bf9c78b450a

El servidor ahora busca los X-Sessions 's en su tienda de sesión. Realiza el mismo hash de los encabezados y el cuerpo de la solicitud y luego verifica si el hash coincide con el valor de X-Auth , si el servidor asume que el cliente está autorizado y responde en consecuencia.

HTTP/1.1 200 OK

El cliente sabe que el servidor tiene el mismo Verifier y lo almacena en localStorage usando el valor de X-Session para la clave, para futuras solicitudes.

Preocupaciones

Soy un desarrollador promedio y no soy experto en criptografía y, según tengo entendido, no puedo ver ningún problema que pueda ocurrir con este método.

Puedo ver las grandes ventajas, como:

  1. La contraseña nunca se envía a través del cable. Evite que MITM obtenga su contraseña.

  2. MITM no puede modificar la solicitud, ya que se revisa con el verificador y luego se envía.

  3. El servidor no necesita usar bcrypt cada vez que un usuario quiera autenticar.

pregunta jamcoope 02.10.2013 - 16:54
fuente

3 respuestas

6
  

La autenticación se realiza a través de una conexión http no segura utilizando AJAX.

Te detengo aquí mismo. Si el código de Javascript que se ejecuta en el lado del cliente pasó por HTTP no seguro, entonces ese código podría haber sido alterado en tránsito por cualquier medio competente atacante Man-in-the-Middle . Luego puede hacer muchas cosas malas, como, por ejemplo, enviar una copia de la contraseña del usuario a un servidor controlado por un atacante.

La criptografía del lado del cliente en Javascript solo funciona si dicho Javascript se realizó a través de un enlace seguro, es decir, HTTPS. Y si tiene ese enlace, ¿por qué molestarse más?

Aparte de eso, lo que describe no tiene nada de "SRPish". SRP es un protocolo de Password Authenticated Key Exchange , lo que significa que otorga inmunidad contra ataques de diccionario sin conexión, algo que no puede lograrse con herramientas de criptografía simétrica como funciones hash y bcrypt. En el mejor de los casos, bcrypt otorgará a resistencia contra los ataques de diccionario sin conexión, lo que significa que un intruso que espía a una conexión puede aprender lo suficiente como para "probar contraseñas en casa", pero sufrirá por cada prueba.

SRP hace "mejor" a través de algunas matemáticas adicionales. Consulte el RFC . Hay exponenciales modulares allí.

SRP-with-TLS solo tiene sentido porque funciona directamente a nivel de SSL, lo realiza el navegador, y utiliza una implementación que ya está ya en el lado del cliente. Cuando el navegador no implementa el SRP en el nivel SSL, vuelve a la configuración "habitual" con SSL normal (con un certificado de servidor) y envía la contraseña del usuario "tal cual" a través de SSL.

    
respondido por el Thomas Pornin 02.10.2013 - 17:07
fuente
2

Está enviando un hash de contraseña en el cable al servidor. Si su base de datos, que almacena el hash y el salt, es hackeada, el pirata informático enviará solo el valor requerido utilizando su propio JavaScript y engañará al servidor.

Entonces, si está haciendo esto en https, hay un mejor enfoque para enviar la contraseña al servidor y hacer hashing. Ya que SSL / TLS es seguro para garantizar que solo el servidor podrá ver la contraseña y todos deben confiar en el servidor para hacer su bit correctamente (es decir, generar hash con sal de la contraseña y compararlo con el valor de db). Y si este es su enfoque, estoy seguro de que no necesita reinventar la rueda. Cualquiera que sea la biblioteca que esté utilizando, esta implementación estará allí.

    
respondido por el user2290134 20.05.2014 - 08:24
fuente
1

Si envía una versión con hash de la contraseña para autenticarse, el hash se convierte en la contraseña. He visto esto antes, y no funciona.

  • El hash no está diseñado para evitar un ataque Man in the middle, se usa para evitar que una base de datos robada se convierta en una lista de contraseñas.
  • Parece que está perdiendo sal del lado del servidor, lo que significa que es más fácil pasar los hashes en su base de datos
  • Un hombre en el medio podría modificar la respuesta del servidor, estableciendo tanto X-Salt como X-R2 en la cadena vacía. Si previamente han interceptado el X-R1, solo tienen que usar la fuerza bruta de la contraseña del usuario para pasar el hash (el código de hash que el cliente envía al servidor después de la respuesta falsa del servidor). Entonces vuelves al punto uno.

Estás intentando implementar tu propio esquema de encriptación, y eso es genial para aprender cómo funciona esto. No lo hagas en producción. No lo hagas Cientos de personas pasaron años haciendo SSL / TLS. Úsalo.

Quieres algo como esto en lugar de X-R1 y X-R2:

enlace

    
respondido por el glidersecurity 03.10.2013 - 02:38
fuente

Lea otras preguntas en las etiquetas