¿Vale la pena usar contraseñas hash en el lado del cliente?

132

Cuando quiero establecer un sistema de inicio de sesión, siempre comparo el MD5 de la contraseña dada con su valor en la tabla de usuarios en el lado del servidor.

Sin embargo, un amigo mío me dijo que un software de red podía rastrear una contraseña "clara".

Entonces mi pregunta es: ¿es una buena idea usar la contraseña en el lado del cliente? ¿Es mejor que hacer hash en el lado del servidor?

Zakaria
fuente
1
Estaba pensando en descifrar la contraseña en el lado del cliente, pero solo así puedo estar seguro de que la contraseña del cliente nunca existe como texto claro en el lado del servidor, lo que significa que pueden sentirse más fáciles al saber que no conozco su contraseña real, o no puede renunciar fácilmente si se ve comprometido. ¿estoy loco?
Ciclón
1
Solo para completar, ya que estamos hablando de seguridad, y MD5 fue mencionado en el OP: siempre se debe usar una sal al cifrar una contraseña. Usar MD5 simple y sin sal es marginalmente mejor que almacenar contraseñas de texto sin formato en su base de datos.
sffc
1
@Cyclone Hashing SOLO en el lado del cliente es definitivamente una mala idea, ya que si el atacante de alguna manera conoce el hash, puede usarlo para iniciar sesión como si supiera la contraseña, omitiendo el código de hash del lado del cliente.
Teejay
55
@Teejay: Por eso no envías el hash en claro. El servidor envía una sal aleatoria al cliente, usted agrega el hash de la contraseña, y vuelve a hacer el hash completo, luego lo envía de vuelta al servidor que realiza el mismo cálculo. Un ataque de repetición falla porque la sal será diferente
MSalters
2
¿No debería haber terminado esta pregunta en security.stackexchange.com?
efr4k

Respuestas:

115

Básicamente, tu amigo tiene razón. Pero simplemente descifrar la contraseña en el lado del cliente es simplemente mejor que enviarla como texto sin formato al servidor. Alguien que puede escuchar sus contraseñas de texto sin formato también puede escuchar las contraseñas con hash y usar estos hashes capturados para autenticarse en su servidor.

Para este asunto, los protocolos de autenticación más seguros generalmente saltan a través de varios aros para asegurarse de que tal ataque de repetición no pueda funcionar, generalmente, al permitir que el cliente seleccione un grupo de bits aleatorios, que se combinan junto con la contraseña , y también enviado en claro al servidor.

En el servidor:

  • generar algunos bits de azar
  • enviar estos bits (en texto claro) al cliente

En el cliente:

  • generar algunos bits aleatorios
  • concatenar contraseña, los bits aleatorios del servidor y los bits aleatorios del cliente
  • generar hash de lo anterior
  • enviar bits aleatorios (en texto claro) y hash al servidor

Como el servidor conoce su propia información aleatoria, así como los bits aleatorios del cliente (los obtuvo como texto claro), puede realizar esencialmente la misma transformación. Este protocolo asegura que nadie que escuche en esta conversación pueda usar la información más tarde para autenticarse falsamente usando la información grabada (a menos que se use un algoritmo muy débil ...), siempre que ambas partes generen diferentes "bits de ruido" cada vez, Se realiza el apretón de manos.

Editar Todo esto es propenso a errores y tedioso y algo difícil de corregir (léase: seguro). Si es posible, considere usar implementaciones de protocolos de autenticación ya escritas por personas conocedoras (¡a diferencia de mí! Lo anterior es solo de la memoria de un libro que leí hace algún tiempo). Realmente no desea escribir esto usted mismo por lo general.

Puñal
fuente
55
¿Cómo puede autenticarse con la contraseña cifrada en el sistema de inicio de sesión, ya que se volverá a cifrar?
Zakaria
44
Si almacena sus contraseñas en forma de hash en el servidor (como debería), entonces el cliente tendrá que cambiar la contraseña dos veces: primero, solo la contraseña, para que coincida con la visión del mundo del servidor, y luego como se describió anteriormente para por el bien del protocolo.
Dirk
3
@Dirk, dado que el atacante puede oler en ambos sentidos, los "bits aleatorios" se olfatearían. Luego, el atacante puede analizar (leer: fuerza bruta) el par de solicitud y respuesta fuera de línea para encontrar la contraseña original.
Pacerier
77
Sin embargo, con el fin de enviar una contraseña o el hash de una contraseña, a menudo se utiliza un proceso asimétrico como Diffie-Hellman para establecer una clave de encriptación que permite a ambas partes intercambiar información sin que una parte de espionaje pueda descifrarla. Esto es exactamente lo que hace SSL, y es la razón por la cual la mayoría de los sitios tienen su página de inicio de sesión en HTTPS / SSL. SSL ya protege contra ataques de repetición. Recomendaría aprovechar SSL en lugar de crear su propio protocolo. Aunque estoy de acuerdo con la salazón + hash del lado del cliente de la contraseña, pero los envío a través de una conexión SSL establecida.
AaronLS
14
Para que quede claro: si no está utilizando HTTPS, no importa qué javascript ejecute en el cliente; un MITM podría modificar el contenido de su página antes de que llegue al cliente. HTTPS es la única solución.
aidan
60

En primer lugar, esto NO mejora la seguridad de su aplicación (suponiendo que sea una aplicación web).

Use SSL (o en realidad TLS, que comúnmente se llama SSL), no es realmente costoso (Mida el tiempo que está usando para encontrar formas de evitarlo y multiplíquelo con el salario mínimo, comprar un certificado casi siempre gana).

El por qué de esto es simple. TLS resuelve un problema (cuando se usa con certificados comprados, no autofirmado) que es bastante grande en criptografía: ¿Cómo sé que el servidor con el que estoy hablando es el servidor con el que creo que estoy hablando? Los certificados TLS son una forma de decir: "Yo, la autoridad de certificación, en la que confía su navegador, certifica que el sitio web en [url] tiene esta clave pública, con una clave privada correspondiente, que (clave privada) solo el servidor conoce, mira Firmé mi firma en todo el documento, si alguien lo modificó, puedes verlo ".

Sin TLS, cualquier cifrado se vuelve inútil, porque si me siento a tu lado en una cafetería, puedo hacer que tu computadora portátil / teléfono inteligente piense que soy el servidor y MiTM (Man in The Middle). Con TLS, su computadora portátil / teléfono inteligente gritará "CONEXIÓN NO CONFIABLE", porque no tengo un certificado firmado por la autoridad de certificación que coincida con su sitio. (Cifrado vs. Autenticación).

Descargo de responsabilidad: los usuarios tienden a hacer clic a través de estas advertencias: "¿Conexión no confiable? ¿Qué? ¡Solo quiero mis fotos de gatitos! Agregar excepción Haga clic en Confirmar Haga clic ¡YAY! ¡Gatitos!"

Sin embargo, si realmente no desea comprar un certificado, implemente el hashing javascript del lado del cliente (y use la biblioteca standford (SJCL) para eso, NUNCA IMPLEMENTE CRYPTO USTED MISMO ).

¿Por qué? Reutilización de contraseña! Puedo robar su cookie de sesión (lo que me permite fingir ante su servidor que soy usted) sin HTTPS fácilmente (vea firesheep). Sin embargo, si agrega un javascript a su página de inicio de sesión que, antes de enviar, codifica su contraseña (use SHA256, o incluso mejor, use SHA256, envíeles una clave pública que generó y luego cifre la contraseña cifrada con eso, no puede usar una sal con esto) y luego envía la contraseña cifrada / cifrada al servidor. REHASH el hash en su servidor con sal y compárelo con lo que está almacenado en su base de datos (almacene la contraseña de esta manera:

(SHA256(SHA256(password)+salt))

(guarde la sal como texto sin formato en la base de datos también)). Y envíe su contraseña así:

RSA_With_Public_Key(SHA256(password))

y verifique su contraseña de esta manera:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

Porque, SI alguien está oliendo su cliente, que será capaz de iniciar una sesión a su cliente (secuestro de sesión) pero serán NUNCA ver la contraseña en texto plano (a menos que alteran su Javascript, sin embargo, un Starbucks hacker probablemente no saber howto / interesará en esto.) Para que tengan acceso a su aplicación web, pero no a su correo electrónico / facebook / etc. (para lo cual sus usuarios probablemente usarán la misma contraseña). (La dirección de correo electrónico será su nombre de usuario o se encontrará en su perfil / configuración en su aplicación web).

FriendlyCryptoNeighbor
fuente
Creo que esta es una buena respuesta, pero probablemente necesite más información sobre cómo saltear correctamente y que es mejor usar una función de hash "lenta" antes de almacenar la contraseña en el servidor (como bcrypt).
Neyt
24

Es probable que esté bien que no se preocupe por esto, ya que Dirk menciona que incluso si utiliza las claves de un hash, un usuario malintencionado podría estar en una red y ver cómo se envía el hash, y simplemente podría enviar el mismo hash.

Es un poco mejor, ya que evita que el usuario malintencionado sepa cuál es la contraseña, pero dado que aún pueden iniciar sesión (o potencialmente reconstruir la contraseña original ), eso no es tan útil.

En general, si le preocupa la seguridad de las contraseñas y los datos de su usuario (¡y debería estarlo!), Querrá usar un servidor SSL seguro. Si esto no es una preocupación para usted por cualquier razón, es mejor que no se moleste con el hash; es solo seguridad a través de la oscuridad .


Editar agosto de 2014: Google está presionando cada vez más para que los sitios web cambien a HTTPS en todas partes , porque asegurar la comunicación en sí es la única forma de evitar ataques de detección de redes. Los intentos de ofuscar los datos transmitidos solo obstaculizarán, no detendrán, a un atacante dedicado, y pueden dar a los desarrolladores una falsa sensación de seguridad peligrosa.

dimo414
fuente
Creo que su opinión de que el hashing del cliente es solo "un poco mejor" es cierto si solo se centra en obtener xla contraseña del usuario y acceder a un solo servicio. Si considera el efecto colectivo, diría que es "mucho mejor"; porque evita la creación de grandes bases de datos de búsqueda de contraseñas utilizadas para forzar hashes salados a través de múltiples servicios. OMI Vea lo que AWS Cognito hace en el cliente como referencia.
f1lt3r
17

En realidad, no estoy de acuerdo con que el hash del lado del cliente sea más seguro en este caso. Creo que es menos seguro.

El punto completo de almacenar un hash de la contraseña en su base de datos en lugar de la contraseña real (o incluso una contraseña cifrada) es que es matemáticamente imposible obtener la contraseña original de un hash (aunque en teoría es posible obtener una colisión entrada hash, cuya dificultad depende de la seguridad del algoritmo hash). El posible vector de ataque aquí es que si un posible atacante de alguna manera compromete su base de datos de almacenamiento de contraseñas, aún no podrá obtener las contraseñas originales de sus usuarios.

Si su mecanismo de autenticación envía un hash de la contraseña, entonces, en este escenario de violación de seguridad, el atacante no necesita saber la contraseña real: solo envía el hash que tienen y, oye, tienen acceso a la cuenta de un usuario en particular, y por extensión, todo su sistema. ¡Esto derrota completamente el punto de almacenar una contraseña hash en primer lugar!

La forma realmente segura de hacerlo es enviar al cliente una clave pública única para que cifre la contraseña, luego la descifra y la vuelve a cifrar en el lado del servidor.

Por cierto, este tipo de pregunta probablemente obtendrá respuestas más expertas sobre Security StackExchange.

Adam Burley
fuente
3
Completamente de acuerdo con esto. Para que un enfoque del lado del cliente funcione, uno también tendría que enviar la sal al cliente, lo que invalidaría todo el propósito de la salazón.
James Wright
@JamesWright: El punto es enviar una sal aleatoria para cada uso, lo que evita la reutilización ilegal de mensajes de inicio de sesión. (Una forma de ataques de repetición). Enviar la misma sal cada vez no tiene sentido.
MSalters
Lo que debe hacer es usar un "nonce" ( en.wikipedia.org/wiki/Cryptographic_nonce ). De esa manera, el servidor también controla la sal y lo hace seguro. El hash en el lado del cliente también es importante para que el código JS inyectado no pueda encontrarlo fácilmente más tarde. Más aquí: stackoverflow.com/a/21716654/43615
Thomas Tempelmann
Para usar salt + nonce en un proceso de autenticación de inicio de sesión, consulte esta respuesta: stackoverflow.com/a/24978909/43615
Thomas Tempelmann
Obviamente, si lo hash en el lado del cliente, tendrás que hacerlo de nuevo en el lado del servidor para evitar el punto que estás haciendo. Sin embargo, como otros señalan, para la privacidad ya desea un cifrado del lado del cliente.
Daniel Methner
5

Tenga en cuenta que mantener las contraseñas seguras contra terceros no es todo lo que hay que hacer.

Tan pronto como la privacidad está involucrado (y cuando cada vez que no es, en estos días?) Que no quieren saber la contraseña. No puede abusar o filtrar lo que no tiene , por lo que tanto usted como sus clientes pueden dormir mejor si nunca ven sus contraseñas de texto sin cifrar.

Por lo tanto, el cifrado / cifrado del lado del cliente tiene sentido.

Rafael
fuente
¡Convenido! Mucha gente pierde este punto. Si descargo su base de datos de contraseñas con contraseñas hash saladas, y puedo descifrar solo una usando una base de datos de búsqueda hash, entonces es probable que pueda descifrarlas todas. Una vez que tengo 50k contraseñas originales, ahora tengo la clave para los xusuarios en nservicios que solo cifran en el servidor. Si cada servicio codifica la contraseña de forma exclusiva antes de abandonar el cliente, la gran base de datos de contraseñas de servicio cruzado se vuelve mucho, mucho más pequeña. Verifique su tráfico de inicio de sesión de AWS, vea lo que hacen. Es probable mi querido Watson.
f1lt3r
1

He estado trabajando mucho en esto recientemente, IRL, hay dos problemas con el cifrado simétrico / hash del lado del cliente que realmente mata la idea: 1. Tienes que devolver la sal al servidor DE ALGUNA VEZ ... y cifrar En el lado del cliente, necesitaría una contraseña ... que anula el propósito. 2. Expones tu implementación de hashing (no es una GRAN oferta, ya que la mayoría de los sitios usan uno de 3 o 4 algos de hashing) lo que hace que el ataque sea más fácil (ya que solo necesitas probar uno en lugar de n).

A lo que finalmente fui fue al cifrado asimétrico en el cliente usando OpenPGP.js o similar ... Esto se basa en una clave importada o generada por el lado del cliente en el cliente y el servidor que envía su clave pública. Solo la clave pública del cliente puede devolverse al servidor. Esto protege contra ataques MIM y es tan seguro como el dispositivo (actualmente guardo la clave privada del cliente de forma predeterminada en localStore, es una demostración).

La principal ventaja de esto es que nunca tengo que tener los datos de los usuarios almacenados / incluso en la memoria sin cifrar en mi servidor / almacén de datos (y la clave privada de mi servidor está físicamente separada)

La base de esto fue proporcionar a las personas una forma de comunicarse de forma segura donde HTTPS estaba restringido (por ejemplo, Irán / Corea del Norte atc ...) y también un experimento divertido.

Estoy LEJOS de ser el primero en pensar en esto, http://www.mailvelope.com/ usa esto

ScottGal
fuente
1

Si alguien puede ver los datos dentro y fuera de su conexión, la autenticación no lo salvará. En cambio, haría lo siguiente para cosas súper secretas.

Las contraseñas se introducen previamente en el lado del cliente antes de enviarse al servidor. (El servidor almacena otro valor hash y salado de ese hash enviado desde el navegador).

Por lo tanto, un ataque de intermediario podría permitirles enviar el mismo valor hash para iniciar sesión que ellos, pero la contraseña de los usuarios no se conocería. Esto les impediría probar otros servicios con las mismas credenciales para iniciar sesión en otro lugar.

Los datos de los usuarios también están encriptados en el lado del navegador.

Ah, entonces un ataque de intermediario obtendría los datos cifrados, pero no podría descifrarlos sin la contraseña real utilizada para iniciar sesión. (contraseña de los usuarios almacenada en el DOM en el navegador cuando iniciaron sesión). Entonces el usuario real vería el contenido descifrado pero el intermediario no podría. Esto también significa que cualquier NSA u otra agencia no podría solicitarle a usted / compañía / proveedor de alojamiento que descifre estos datos, ya que también sería imposible para ellos hacerlo.

Algunos pequeños ejemplos de ambos métodos están en mi blog http://glynrob.com/javascript/client-side-hashing-and-encryption/

GlynRob
fuente
1

Recientemente, tanto GitHub como Twitter anunciaron que las contraseñas se almacenaban en registros internos. Esto sucedió inadvertidamente en informes de errores y otros registros que se abrieron paso hacia splunk, etc. gran cosa ya que los administradores no tendrían mucho uso para ello. Independientemente de que sean administradores, no nos gusta ver las contraseñas.

Entonces, la pregunta es realmente si el hash debe suceder en el lado del cliente por seguridad, pero ¿cómo podemos proteger la contraseña antes de que finalmente se convierta en hash y se compare en el lado del servidor para que no se registre de alguna manera?

El cifrado no es una mala idea porque los desarrolladores al menos tienen que saltar algunos obstáculos, y si encuentra que las contraseñas entraron en los registros, simplemente puede cambiar la clave de cifrado, destruir el original y esos datos se vuelven inútiles. Mejor aún, gire las teclas todas las noches y podría reducir las ventanas en gran medida.

También puedes hacer un hash en tu registro de usuario. Las contraseñas filtradas serían contraseñas de texto sin formato hash. El servidor almacenaría una versión hash del hash. Seguro, el hash se convierte en la contraseña, pero a menos que tenga una memoria fotográfica, no recordará un bcyrpt de 60 caracteres. Sal con el nombre de usuario. Si pudiera reunir algo sobre el usuario durante el proceso de inicio de sesión (sin exponer que existe el registro de usuario), también puede aprovechar eso creando un hash más robusto que no se podría compartir entre sitios. Ningún hombre en el medio podría cortar y pegar el hash capturado entre sitios.

Combínelo con una cookie que no se envíe de vuelta al servidor y podría estar en algo. En la primera solicitud, envíe una cookie al cliente con una clave, luego asegúrese de que la cookie no regrese al servicio de inicio de sesión con tan pocas posibilidades de que se registre. Almacene la clave en un almacén de sesión y luego bórrela justo después de que se inicie sesión o cuando la sesión haya expirado ... esto requiere un estado para ustedes, JWT, pero tal vez solo usen un servicio nosql para ello.

Entonces, en el futuro, un administrador se encuentra con una de estas contraseñas cifradas y hash en splunk o una herramienta de informe de errores. Debería ser inútil para ellos, ya que ya no pueden encontrar la clave de cifrado, e incluso si lo hicieron, entonces tienen que forzar un hash por fuerza bruta. Además, el usuario final no envió ningún texto sin formato a lo largo de la línea, por lo que cualquier hombre en el medio al menos tiene más dificultades y no puede simplemente saltar a otro sitio e iniciar sesión.

Eric Twilegar
fuente
Exactamente mi preocupación. Si el servidor de alguna manera se registra por accidente debido a una implementación deficiente o una intención maliciosa, entonces es posible que otra cuenta del usuario pueda verse comprometida si reutiliza las contraseñas.
Dan
0

Considera esto:-

El cliente envía una solicitud al servidor "Tengo una contraseña para validar".

El servidor envía al cliente una cadena aleatoria única. R $

El cliente incrusta la contraseña del usuario en esta cadena (según las reglas (variables) que desee aplicar).

El cliente envía la cadena al servidor y, si la contraseña es correcta, el servidor inicia sesión en el usuario.

Si el servidor recibe otra solicitud de inicio de sesión con R $, el usuario se desconecta y la cuenta se congela en espera de investigación.

Obviamente, se tomarían todas las otras precauciones de seguridad (normales).

necesidades
fuente
0

Esta idea del hash del lado del cliente es proteger al usuario, no a su sitio. Como ya se mencionó muchas veces, tanto el texto sin formato como las contraseñas hash tienen acceso a su sitio por igual. No obtienes un beneficio de seguridad.

Pero la contraseña real de sus usuarios solo debe ser conocida por ellos. Saber qué eligieron como contraseña es información que se puede utilizar en su contra en otros sitios y sistemas. Está siendo un sitio centrado en el cliente al protegerlos de que sus desarrolladores de servidores o terceros descubran su elección de contraseña.

n8isjack
fuente