Alternativas para enviar contraseñas de texto sin formato al iniciar sesión

Jan 02 2021

Nota: Ya leí ¿Está bien enviar una contraseña de texto sin formato a través de HTTPS? y seguridad https: ¿la contraseña debe tener hash del lado del servidor o del lado del cliente? , pero aquí se trata de un método de reemplazo específico (ver más abajo).


Después de leer un artículo sobre un nuevo método de autenticación en el blog de Cloudflare , miré las POSTsolicitudes que se envían durante la autenticación con "Herramientas de desarrollo> Red". Muchos sitios web populares (Reddit, HN, etc.) aún envían la contraseña en texto plano en la POSTsolicitud ( protegida por SSL) (vea la captura de pantalla a continuación).

¿Este método de inicio de sesión sigue siendo estándar en la industria?

¿Es la siguiente alternativa más segura que enviar una contraseña en texto plano a través de HTTPS?

  • signup: el cliente genera un aleatorio salty envía la tupla a (username, salt, hash(plain_password + salt))través de una POSTsolicitud. Entonces, la contraseña de texto sin formato nunca llega al servidor.

  • inicios de sesión subsiguientes: el servidor tiene que enviar de saltvuelta a cualquier cliente que intente iniciar sesión con un determinado username, para que el cliente pueda hacer hash con la misma sal. Esto significa que el servidor se lo está revelando salta cualquiera que intente iniciar sesión con un nombre de usuario determinado.

  • Beneficio: el servidor almacena una contraseña con hash + salteada (que es estándar) pero también el servidor nunca, nunca, ha visto la contraseña de texto plano ni una sola vez (por lo que si el servidor está comprometido, el riesgo es limitado)

Notas:

  • dado que H = hash(plain_password + salt)ahora se comporta un poco como un nuevo plaintext(consulte la segunda respuesta de Prueba de contraseña de conocimiento cero: ¿por qué el hash de la contraseña en el lado del cliente no es un ZKP? ), entonces el servidor puede almacenar (username, salt, server_salt, hash(H + server_salt))en la base de datos, en lugar de (username, salt, H).

  • Para mitigar los riesgos de ataques de repetición, el servidor también puede enviar un único nonce, junto con saltcada inicio de sesión, que expira después de un intento de inicio de sesión.

  • el objetivo principal aquí es que el servidor nunca tenga acceso a la contraseña de texto sin formato o un simple hash de la misma (que a menudo podría revertirse con una sola tabla de arco iris para todo el sitio). Estoy de acuerdo con el riesgo de que un atacante tenga que calcular una tabla de arco iris por usuario .

  • Ejemplo de ataque que me gustaría mitigar: si el servidor tiene acceso a una contraseña de texto sin formato y está comprometido (por ejemplo, Spectre / Meltdown vuln.), Entonces la contraseña de texto sin formato del usuario (posiblemente reutilizada en otros sitios web) podría ser robada, antes de que sea salada. -hashed y guardado en la base de datos.


Respuestas

14 SteffenUllrich Jan 02 2021 at 14:38

No veo cómo su propuesta es mejor que los enfoques de hash del lado del cliente existentes, pero la encuentro más compleja de implementar que otras. Desafortunadamente, no describe un riesgo específico al que está intentando acceder, así que asumo las amenazas típicas que se ven comúnmente.

Hombre en el atacante de en medio

En este caso, se supone que algún hombre en el medio tiene acceso al tráfico, por ejemplo, porque comprometió la interceptación de TLS de tráfico confiable en un firewall corporativo o se apoderó de una CA confiable como en el caso de superfish .

En este escenario, el atacante obtiene acceso al Hmismo que antes con plain_password. Dado que Hes todo lo que se necesita para la autenticación, el atacante tiene éxito y su enfoque no agrega ninguna protección adicional aquí .

Ocultar contraseñas débiles y reutilización de contraseñas

Un argumento común para el hash del lado del cliente es no exponer una contraseña débil o reutilizada al servidor, sino autenticarse con una contraseña derivada compleja. Su enfoque hace con el hash plain_passwordcon algún usuario generados al azar salty luego enviar Hy saltal servidor de configuración de la contraseña.

Si bien esto funciona, cada autenticación ahora requiere un paso adicional : primero necesita recuperar del usuario la sal utilizada anteriormente para el usuario y luego puede usar esto saltpara hacer hash del archivo plain_password. Este paso adicional hace que la autenticación sea más compleja, ya que primero debe verificar al usuario con el servidor y luego puede verificar la contraseña. Además, una implementación trivial de esto abre una fuga de información ya que permite verificar si el usuario existe en primer lugar (se devolvió sal o no) sin más autenticación.

Esta fuga de información puede ser cerrada por el servidor devolviendo algo de sal sin importar si el usuario existe o no. Por supuesto, esto no puede ser solo una sal aleatoria, ya que de lo contrario un atacante podría simplemente verificar dos veces al mismo usuario y concluir que el usuario no existe si la sal devuelta es diferente. Por lo tanto, la sal debe ser corregida para el usuario inexistente, es decir, derivada del nombre de usuario.

Y esto también muestra una ruta para simplificar su enfoque : en lugar de generar una sal aleatoria por parte del usuario, almacenarla en el servidor y recuperarla más tarde, se podría simplemente derivar la sal del nombre de usuario en el lado del cliente . Un simple salt=hash(username+domain)sería suficiente para generar una sal que es único por dominio y por lo tanto hacer que tanto salty Hdiferente, incluso si usernamey plain_passwordconseguir reutilizados en diferentes dominios. Y, contrariamente a su enfoque, no se necesita un viaje adicional al servidor para recuperar primero la sal utilizada anteriormente para el usuario.


En resumen: este enfoque simplificado es básicamente enviar en hash(plain_password+username+domain)lugar de la contraseña original. El dominio se agrega para asegurarse de que incluso si usernamey plain_passwordse reutilizan en varios sitios, la contraseña derivada no se reutiliza.

8 mti2935 Jan 02 2021 at 21:33

Este es exactamente el problema que los protocolos como PAKE y SRP pretenden resolver. Con PAKE / SRP, el cliente y el servidor se autentican mutuamente basándose en una contraseña conocida por el cliente (y una derivación de la contraseña conocida por el servidor).

El cliente demuestra al servidor que conoce la contraseña, sin que el cliente envíe la contraseña (o datos equivalentes a la contraseña) al servidor. Al final del proceso, el cliente y el servidor comparten un secreto compartido.

El servidor no almacena la contraseña (o datos equivalentes a la contraseña) y no es susceptible a ataques de diccionario. Un fisgón o un intermediario capaz de ver el texto sin formato enviado a través del cable no puede obtener suficiente información para derivar la contraseña. Esto evita eficazmente los ataques de intermediarios mediante certificados falsos y evita que los sitios de 'phishing' roben las contraseñas de los usuarios.

Para obtener una buena descripción de cómo 1password implementó SRP, consulte https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/

5 mentallurg Jan 02 2021 at 16:00

Además de la respuesta de Steffen Ullrich :

Si durante el inicio de sesión el usuario envía solo el hash, el atacante no necesita saber la contraseña. Basta con robar la base de datos de contraseñas. Luego, durante la solicitud de inicio de sesión, el atacante simplemente enviará el hash desde la base de datos. El servidor no distinguirá si el cliente usó la contraseña y la codificó, o si el cliente (atacante) simplemente envió el hash.

El artículo sobre OPAQUE aborda también este problema: robar la base de datos de contraseñas no ayudará al atacante. Uno necesitaría saber la contraseña de usuario simple.

3 MargaretBloom Jan 03 2021 at 08:43

Si el atacante comprometió su servidor, ellos tienen el control no solo del software que se ejecuta en su servidor, sino también del software que se ejecuta en los clientes.
Independientemente del esquema de autenticación bellamente diseñado que haya diseñado, el atacante puede modificarlo antes de enviarlo al navegador.
Ahora tiene un problema de huevo-gallina: no puede asegurar una contraseña si el atacante controla la forma en que se recopila y envía a su servidor.

Si está preocupado por una violación de datos, su método funcionaría como protección, pero también lo haría un servidor de hash de contraseña adecuado.

Si le preocupan los ataques MITM, TLS los resuelve.
Si le preocupan los ataques MITM sobre TLS, entonces, como me gusta decir, una buena defensa contra ellos siempre comienza con un manual de Krav Maga. Un atacante que tiene suficientes recursos para romper TLS consistentemente no tiene problemas para obtener lo que quiere de cualquier persona que no esté debidamente capacitada y especialmente entrenada (sí, estoy hablando de tortura, chantaje, secuestro y asesinato).

Si le preocupa un actor de amenazas que solo puede leer los datos recibidos por el servidor, entonces su enfoque (corregido por Steffen) funcionará en su contra. Sin embargo, esta es una circunstancia extraña y poco común, que a menudo surge de un servidor muy mal configurado y malas prácticas de desarrollo (es decir, enviar credenciales sobre solicitudes GET y almacenar el registro de acceso públicamente). Es más fácil corregir estos errores que inventar un protocolo solo para lidiar con ellos.

Tenga en cuenta que las dos vulnerabilidades que mencionó (en realidad es solo una, ya que Meltdown es técnicamente una variante de Spectre) eventualmente resultarían en una escalada de privilegios local, lo que le da al atacante el control total de su servidor web. Destacando nuevamente lo raro que es el escenario en el que un atacante tiene acceso de solo lectura a los datos recibidos por su servidor web.

Entonces, la razón por la que muchos sitios importantes no lo usan es porque no agrega prácticamente nada, excepto en circunstancias específicas que probablemente sean configuraciones incorrectas. También vale la pena señalar que si un atacante puede leer qué datos se están transfiriendo en su servidor, usted está en el lado perdedor del juego. Fíjense, es bueno tener protecciones en capas, pero su principal objetivo no es que suceda en primer lugar. Y concentrarse en eso también le evitaría inventar nuevos esquemas.

De todos modos, como mostró Steffen, su esquema propuesto podría funcionar nuevamente con un modelo de ataque tan extraño. Todavía usaría en hash(hash(domain + username) + password)lugar de hash(domain + username + password)simplemente descartar la posibilidad remota de que domain + username + passwordtodavía sea una palabra en un diccionario.
Como mostró mti2935, SRP es una alternativa más interesante. La autenticación basada en certificados (es decir, la que maneja el navegador) es otra opción (que encuentro mejor que hacerlo manualmente en un script JS potencialmente contaminado, como parece haber propuesto en los comentarios).