¿Debo hash la contraseña antes de enviarla al servidor?

110

Noté que la mayoría de los sitios envían las contraseñas como texto sin formato a través de HTTPS al servidor. ¿Hay alguna ventaja si en lugar de eso envío el hash de la contraseña al servidor? ¿Sería más seguro?

Jader Dias
fuente
5
@Jader Dias: Sé que no preguntaste esto, pero no sería más seguro si lo escribes, ENTONCES envíalo por https. De hecho, podría hacerlo menos seguro, ya que expone su sal. Además, (hablando de mi parte trasera aquí), la combinación de algoritmos podría causar más colisiones de hash y hacerlo más pirateable.
Merlyn Morgan-Graham
@Merlyn "colisiones hash" ¡buen punto!
Jader Dias
La combinación de algoritmos no aumenta la probabilidad de colisión en absoluto. Ese es el objetivo de una función hash. Dada cualquier entropía de entrada, devuelve una salida que tiene la misma probabilidad de estar en cualquier lugar del posible espacio de salida.
JJ
@JJ "La combinación de algoritmos no aumenta la probabilidad de colisión en absoluto". Realmente me gustaría ver una prueba de esa declaración. Déjame detenerte: esto es falso , en general aumenta las colisiones. Puedo construir fácilmente una función hash tal que h (x) no sea constante 0 sino h (h (x)) = 0 para todo x. Por lo tanto, debería consultar el conjunto exacto de algoritmos hash y cómo los mezcla. Entonces necesitaría probar su declaración. AFAIK incluso para múltiples SHA (con sal), este es un problema abierto. Y básicamente creemos que esto es cierto. La criptografía es difícil.
extraño

Respuestas:

155

Esta es una pregunta antigua, pero sentí la necesidad de dar mi opinión sobre este importante asunto. Hay tanta desinformación aquí

El OP nunca mencionó enviar la contraseña de forma clara a través de HTTP, solo HTTPS, pero muchos parecen estar respondiendo a la pregunta de enviar una contraseña a través de HTTP por alguna razón. Dicho eso:

Creo que las contraseñas nunca deben conservarse (y mucho menos transmitirse) en texto sin formato. Eso significa que no se guarda en el disco, ni siquiera en la memoria.

Las personas que responden aquí parecen pensar que HTTPS es una bala de plata, pero no lo es. Sin embargo, ciertamente ayuda mucho y debe usarse en cualquier sesión autenticada.

Realmente no es necesario saber qué es una contraseña original. Todo lo que se requiere es una forma confiable de generar (y volver a generar confiablemente) una "clave" de autenticación basada en el texto original elegido por el usuario. En un mundo ideal, este texto debería generar inmediatamente una "clave" mediante hash utilizando sal irreversible. Esta sal debe ser única para la credencial de usuario que se genera. Esta "clave" será la que utilicen sus sistemas como contraseña. De esta manera, si sus sistemas alguna vez se ven comprometidos en el futuro, estas credenciales solo serán útiles para su propia organización y en ningún otro lugar donde el usuario haya sido perezoso y haya utilizado la misma contraseña.

Entonces tenemos una llave. Ahora necesitamos limpiar cualquier rastro de la contraseña en el dispositivo del cliente.

A continuación, necesitamos llevar esa clave a sus sistemas. Nunca debe transmitir una clave o contraseña "en claro". Ni siquiera a través de HTTPS. HTTPS no es impenetrable. De hecho, muchas organizaciones pueden convertirse en un MITM de confianza, no desde una perspectiva de ataque, sino para realizar inspecciones del tráfico para implementar sus propias políticas de seguridad. Esto debilita HTTPS y no es la única forma en que sucede (como redirecciones a ataques HTTP MITM, por ejemplo). Nunca asuma que es seguro.

Para evitar esto, aplicamos un hash a la clave con un único nonce. Este nonce es único para cada envío de una clave a sus sistemas, incluso para la misma credencial durante la misma sesión si necesita enviarla varias veces. Puede revertir este nonce una vez que llegue a sus propios sistemas para recuperar la clave de autenticación y autenticar la solicitud.

En este punto, lo hash irreversiblemente una última vez antes de que se almacene permanentemente en sus propios sistemas. De esa manera, puede compartir la sal de la credencial con organizaciones asociadas a los fines de SSO y similares, al tiempo que puede demostrar que su propia organización no puede hacerse pasar por el usuario. La mejor parte de este enfoque es que nunca compartes nada generado por el usuario sin su autorización.

Investigue más, ya que hay más de lo que yo he divulgado, pero si desea brindar una verdadera seguridad a sus usuarios, creo que este método es actualmente la respuesta más completa aquí.

TL; DR:

Utilice HTTPS. Hash contraseñas de forma segura, irreversible, con una sal única por contraseña. Haga esto en el cliente, no transmita su contraseña real. La transmisión de la contraseña original de los usuarios a sus servidores nunca está "OK" o "Bien". Limpia cualquier rastro de la contraseña original. Utilice un nonce independientemente de HTTP / HTTPS. Es mucho más seguro en muchos niveles. (Respuesta a OP).

usuario3299591
fuente
25
Acabo de revisar gmail y facebook: las herramientas de desarrollo de Chrome me dicen que tanto POST con un mensaje codificado en urlencoded que contiene mi nombre de usuario y contraseña en texto simple (sin sal). ¿Cómo / por qué los grandes jugadores no están usando nonce salating en el cliente?
gremwell
18
Usted hash la clave con un nonce y afirma poder revertir el nonce en el lado del servidor. ¿Estás forzando el hash entonces? O cómo se recupera un nonce cuando se obtiene un hash = HASH (secreto + nonce) HASH debería ser una función irreversible. ¿Ha implementado esto? No creo que lo que explicas sea factible. ¿Puedes crear un diagrama de flujo del protocolo?
Silver
19
Si no confías en HTTPS, ¡cada esfuerzo es inútil! Su código en sí se envía a través del cable y un atacante puede modificar / reemplazar todos sus intentos de asegurar la contraseña en tránsito
Sajid Kalla
3
Un MitM que puede reescribir un certificado puede reescribir el nonce. O lo que dijo Sajid.
leewz
4
Si está preocupado por MITM con HTTPS, ¿cuál es el punto de enviar un salt al cliente para que el cliente pueda salar la contraseña antes de transmitir el hash al servidor? Parece inútil. También podría hacer un hash sin sal en el servidor, luego usar una sal para hash nuevamente en el servidor. Claramente, el cliente tampoco puede ser el generador de la sal de cliente porque el próximo inicio de sesión sería diferente y no calcularía el mismo hash del lado del servidor.
aplastar
24

Dado que es sobre HTTPS, definitivamente está bien enviar la contraseña sin hash (sobre HTTPS no es texto sin formato). Además, si su aplicación depende de HTTPS para mantener su contenido seguro, entonces es inútil aplicar hash a la contraseña antes de enviarla a través de HTTPS (es decir, si un atacante puede desencriptar los datos en el cable, de todos modos está jodido)

Kiersten Arnold
fuente
5
Esto no debería ser un problema. Si el cliente está usando un proxy, entonces todo lo que verá el proxy son los datos encriptados HTTPS. Si está hablando de un ataque man-in-the-middle, un certificado configurado correctamente debería evitarlo.
Kiersten Arnold
7
@Jader: Ninguna cantidad de juguetear con los datos detendrá un ataque MITM, ya que solo puede transmitir lo que se le presente. No importa si está transmitiendo una contraseña o un hash. Eso es un asunto completamente diferente.
David Thornley
2
El propósito de SSL (HTTPS = HTTP sobre SSL) es frustrar MITM.
yfeldblum
1
@carnold - MINTM - ¿Qué pasa con la redirección a http? ¿Se daría cuenta la mayoría de la gente? sslstrip - securityfocus.com/brief/910
nate c
1
@Jader Dias está tratando de detener un problema que no existe. HTTPS detiene este problema, un hash del lado del cliente no agrega ninguna cantidad de seguridad. Nunca se puede confiar en el cliente.
torre
17

No, de hecho esto sería una vulnerabilidad. Si el atacante puede obtener el hash de la base de datos, entonces podría usarlo para autenticarse sin necesidad de descifrarlo. Bajo ninguna circunstancia un usuario o un atacante debe poder obtener una contraseña hash.

El objetivo del hash de contraseñas es agregar una capa adicional de seguridad. Si un atacante puede obtener el hash y la sal de la base de datos utilizando SQL Injection o una copia de seguridad insegura, entonces tiene que encontrar el texto sin formato mediante la fuerza bruta. John The Ripper se usa comúnmente para romper los hashes de contraseñas saladas.

No usar https es una violación de OWASP Top 10: A9-Insufficient Transport Layer Protection

EDITAR: Si en su implementación calcula a sha256(client_salt+plain_text_password)y luego calcula otro hash en el lado del servidor, sha256(server_salt+client_hash)entonces esta no es una vulnerabilidad seria. Sin embargo, todavía es susceptible de escuchar a escondidas y reproducir la solicitud. Por lo tanto, esto sigue siendo una clara violación de WASP A9. Sin embargo, esto todavía utiliza un resumen de mensajes como capa de seguridad.

Lo más parecido que he visto a un reemplazo del lado del cliente para https es un diffie-hellman en el intercambio de claves en javascript . Sin embargo, esto evita los ataques MITM activos y, por lo tanto, es hasta el punto de tecnicismo una violación de OWASP A9. Los autores del código están de acuerdo en que este no es un reemplazo completo de HTTPS, sin embargo, es mejor que nada y mejor que un sistema de hash del lado del cliente.

torre
fuente
4
En realidad, lo volvería a codificar en el servidor, así que edite su respuesta contemplando este escenario.
Jader Dias
@Rook está utilizando el intercambio de claves diffie-hellman junto con https ¿es una solución "inútil"? (Quiero decir que solo podemos usar https y diffie helman no aumentan la seguridad imao)
Michel Gokan
@Michel Kogan se puede utilizar un intercambio de claves DH en HTTP junto con otras herramientas.
torre el
1
@Rook Es una buena práctica aplicar un hash en el servidor, por lo que creo que debería actualizar el comienzo de su respuesta para no descartar el hash del lado del cliente, y solo entonces mencionar que los hash y las sales almacenados en el servidor nunca deben estar expuestos.
Levente Pánczél
8

Enviar un hash a través del cable anula por completo el propósito del hash, porque un atacante puede simplemente enviar el hash y olvidarse de la contraseña. En pocas palabras, un sistema que autentica usando un hash en texto claro es muy abierto y puede verse comprometido con nada más que un rastreo de red.

Paul Keister
fuente
2
Esto parece una tontería total ... ¿Cómo es un hash menos seguro que una contraseña?
Levente Pánczél
1
Esto solo es cierto para los hash "tontos". Considere esto: un servidor envía un salt S al cliente y el cliente hace HASH (S + PASSWORD) y lo envía al servidor. El servidor respeta ese hash específico solo para la sesión actual. Un atacante puede enviar el hash y olvidarse de la contraseña, pero SOLO PARA LA SESIÓN ACTUAL. Por lo tanto, es más seguro que el texto sin formato.
Hola mundo
Actualización: la autenticación de acceso de resumen es aún más sofisticada: en.wikipedia.org/wiki/Digest_access_authentication
Hello World
2
Para ser claro: cuando digo "frustra el propósito del hash" me refiero a la práctica común y segura de hash de contraseñas antes de almacenarlas en una base de datos. Sin embargo, el argumento sostiene que enviar un valor hash en lugar de una contraseña no mejora la seguridad sin pasos adicionales.
Paul Keister
Solo para agregar a lo que dijo Paul: este tipo de ataque se llama un "ataque de repetición" si alguien quiere leer más sobre él en otro lugar.
5

La contraseña en texto plano nunca (ni siquiera cuando se usa HTTPS) deja al cliente. Debe tener un hash irreversible antes de dejar el cliente, ya que no es necesario que el servidor sepa la contraseña real.

El hash y luego la transmisión resuelve los problemas de seguridad para los usuarios perezosos que usan la misma contraseña en varias ubicaciones (lo sé). Sin embargo, esto no protege su aplicación ya que un pirata informático que obtuvo acceso a la base de datos (o de cualquier otra manera pudo obtener el hash), ya que el pirata informático podría simplemente transmitir el hash y hacer que el servidor lo acepte.

Para resolver este problema, por supuesto, puede simplemente aplicar un hash al hash que recibe el servidor y cancelarlo.

Mi enfoque del problema en una aplicación web basada en socket que estoy creando es que en la conexión con el cliente, el servidor genera una sal (cadena aleatoria que se agregará antes del hash) y la almacena en la variable de sockets, luego transmite este hash al cliente. El cliente toma la contraseña de los usuarios, la codifica, agrega la sal del servidor y la codifica todo antes de transmitirla al servidor. Luego se envía al servidor que compara este hash con el hash (hash en el DB + salt). Hasta donde yo sé, este es un buen enfoque, pero para ser justos, no he leído mucho sobre el tema y si me equivoco en algo, me encantaría que me corrijan :)

Victor Zimmer
fuente
3

Use HTTP Digest: protege la contraseña incluso a través de http (pero el mejor uso sería http digest sobre https)

Wikipedia:

La autenticación de acceso de resumen HTTP es uno de los métodos acordados que un servidor web puede utilizar para negociar las credenciales con un usuario web (utilizando el protocolo HTTP). La autenticación implícita está destinada a reemplazar el uso no cifrado de la autenticación de acceso básica, lo que permite que la identidad del usuario se establezca de forma segura sin tener que enviar una contraseña en texto plano a través de la red. La autenticación implícita es básicamente una aplicación de hash criptográfico MD5 con el uso de valores nonce para evitar el criptoanálisis.

Enlace: http://en.wikipedia.org/wiki/Digest_access_authentication

Si desea ver un uso "en la vida real", puede mirar phpMyID, un proveedor de php openid que usa autenticación http digest http://siege.org/phpmyid.php

.. o puede comenzar desde las muestras de autenticación de php en http://php.net/manual/en/features.http-auth.php

Http digest rfc: http://www.faqs.org/rfcs/rfc2617

Según mis pruebas, todos los navegadores modernos lo admiten ...

vlad b.
fuente
HTTP Digest implementa lo que quise decir en esta pregunta, pero ¿tendríamos alguna ventaja si usáramos HTTPS Digest (SSL + HTTP Digest)?
Jader Dias
Una diferencia principal sería que todo se envía / recibe encriptado: los encabezados http se envían y reciben y la respuesta html. Para alguien que intenta "hackear" ssl aleatoriamente usando un ataque man-in-the-middle, el resumen http sería un motivo adicional para hacerle buscar otro objetivo más fácil, o si está registrando todo el tráfico capturado, sus contraseñas son aún más seguras. Puede que haya entendido mal la pregunta, el inglés no es mi primer idioma.
vlad b.
El hash sobre la contraseña tiene una gran ventaja: si el tráfico se registra o se captura de alguna manera, hará el trabajo más difícil para esa persona. Además, con http digest, si no siempre se requiere ssl, puede permitir que los usuarios elijan entre http y https. O puede usar diferentes protocolos para diferentes servidores (por ejemplo, no hago cumplir https para ver / modificar datos menos importantes (nombre de usuario, carga de avatar) pero hago cumplir https en la facturación y otras partes del sitio (de esa manera puedo disminuir la carga en algunos servidores, si es necesario)
vlad b.
3

Si está buscando reemplazar una contraseña de texto sin cifrar a través de HTTPS con una contraseña con hash a través de HTTP, entonces está buscando problemas. HTTPS genera una clave de transacción compartida aleatoria al abrir un canal de comunicación. Eso es difícil de descifrar, ya que está bastante limitado a forzar la clave compartida utilizada para una transacción (relativamente) a corto plazo. Mientras que su hachís se puede olfatear, desconectar y buscar en una tabla de arcoíris o simplemente forzarlo brutalmente durante un largo período de tiempo.

Sin embargo, una ofuscación de contraseña básica del lado del cliente (no hash) enviada a través de HTTPS tiene algún valor. Si no me equivoco, algunos bancos utilizan esta técnica. El propósito de esta técnica no es proteger la contraseña para que no rastree el cable. Más bien, es para evitar que la contraseña sea utilizable para tontas herramientas de espionaje y complementos de navegador que simplemente capturan cada solicitud HTTPS GET / POST que ven. He visto un archivo de registro capturado de un sitio web malicioso que contenía 400 MB de transacciones GET / POST aleatorias capturadas de sesiones de usuario. Puede imaginar que los sitios web que solo usaban HTTPS aparecerían con contraseñas de texto sin cifrar en el registro, pero los sitios web con una ofuscación muy básica (ROT13) también aparecerían con contraseñas que no son de uso inmediato.

Simon en LabSlice-com
fuente
"pero los sitios web con ofuscación muy básica (ROT13) también aparecerían con contraseñas que no son de uso inmediato", esto contradice la declaración original. La clave es que no son INMEDIATAMENTE de uso, pero eso es realmente inútil. La contraseña y su ROT13 son equivalentes. PERO si SHA2 la contraseña, no estará presente en los registros (por lo que sus administradores no llegan a conocer las posibles contraseñas de los usuarios a otros sistemas), y YA NO está violando casi todas las leyes de privacidad.
Levente Pánczél
2

Si está conectado a un servidor https, el flujo de datos entre el servidor y el navegador debe estar cifrado. Los datos son solo texto sin formato antes de enviarse y después de ser recibidos. Artículo de Wikipedia

jac
fuente
¿Los proxies no interceptan estos datos?
Jader Dias
Según tengo entendido, lo hacen, pero el proxy no es responsable del cifrado / descifrado y, a menos que sea un proxy sin escrúpulos, solo transmite los datos. El tipo y la fuerza del cifrado dependen de lo que el servidor y el cliente puedan admitir.
jac
1
Incluso si el proxy no es exorbitante, no puede descifrar los datos ya que están cifrados con la clave pública del servidor. La única forma en que un proxy puede descifrar los datos es falsificar el certificado del servidor con una clave diferente
Kiersten Arnold
@Jader. Si lo hicieran, HTTPS sería bastante patético. cuando se autentica en un servidor con HTTPS, obtiene una garantía (asumiendo que el certificado es válido) de que se está conectando a un determinado servidor y tiene una ruta encriptada de un extremo al otro. Hipotéticamente, un hombre en el medio de un ataque podría engañarlo, por supuesto, pero eso no es lo mismo que un proxy web básico.
Peter Recore
2

Descargo de responsabilidad: no soy un experto en seguridad, y publico con la esperanza de que otros critiquen mi posición como demasiado cautelosa o mejorable y aprenderé de ello. Dicho esto, solo quiero enfatizar que el hash cuando deja a su cliente no significa que no tenga que hacerlo en el backend antes de ponerlo en la base de datos.

Haz ambos

Haz ambas cosas porque:

  1. El hash en el viaje ayuda a cubrir las vulnerabilidades del transporte, si la conexión SSL se ve comprometida, aún no pueden ver la contraseña sin procesar. No importará en términos de poder hacerse pasar por usuarios autorizados, pero protegerá a sus usuarios de que sus contraseñas se lean en asociación con su correo electrónico. La mayoría de las personas no siguen las mejores prácticas y usan la misma contraseña para muchas de sus cuentas, por lo que esto puede ser una vulnerabilidad seria para sus visitantes.

  2. Si alguien, de alguna manera, pudo leer las contraseñas de la base de datos (esto sucede, piense en la inyección SQL), todavía no podrá ejecutar acciones privilegiadas que se hagan pasar por usuarios a través de mi API. Esto se debe a la asimetría hash; incluso si conocen el hash almacenado en su base de datos, no sabrán la clave original utilizada para crearlo y eso es lo que usa su middleware de autenticación para autenticarse. Esta es también la razón por la que siempre debes salar el almacenamiento de hachís.

Por supuesto, podrían hacer muchos otros daños si tuvieran rienda suelta para leer lo que quieran de su base de datos.

Solo quiero enfatizar aquí que si decide usar hash en la clave antes de salir de sus clientes, eso no es suficiente; el hash backend es, en mi opinión, mucho más importante y esta es la razón: si alguien está interceptando el tráfico de su cliente, luego verán el contenido del passwordcampo. No importa si se trata de un hash o de texto sin formato, pueden copiarlo literalmente para hacerse pasar por un cliente autorizado. (A menos que siga los pasos que @ user3299591 describe, y le recomiendo que lo haga). El hash de la columna DB, por otro lado, es una necesidad y no es nada difícil de implementar.

pixelpax
fuente
0

En realidad, sería menos seguro codificar la contraseña y enviarla a través de un canal no cifrado. Expondrá su algoritmo hash en el cliente. Los piratas informáticos podrían simplemente olfatear el hash de la contraseña y luego usarlo para piratear más tarde.

Al usar HTTPS, evita que un pirata informático obtenga la contraseña de una sola fuente, ya que HTTPS usa dos canales, ambos encriptados.

Carter Medlin
fuente
1
En realidad, lo volvería a codificar en el servidor y usaría HTTPS de todos modos, así que edite su respuesta considerando este escenario.
Jader Dias
@Jader, el punto es que todo lo que un atacante necesita ahora es el primer hash, en lugar de una contraseña. En efecto, el hash que toma de la contraseña en el lado del cliente ahora es tan útil como la contraseña misma. Entonces, realmente no está ganando mucha seguridad.
Peter Recore
¿Alguien ha pensado alguna vez en no enviar partes del token? como si conociera sus métodos de hash, ¿por qué enviaría eso? ¿No debería el servidor conocer la clave del cliente para descifrar?
jemiloii
0

Si existe una ventaja y si es más (o menos) seguro, realmente depende de la implementación. Podría decirse que hay alguna ventaja, pero si lo implementa de manera deficiente, definitivamente podría crear una solución que sea menos segura que pasar incluso una contraseña de texto sin formato.

Esto puede verse desde la perspectiva de dos tipos de ataques: uno con acceso al tráfico de la red y otro con acceso a la base de datos.

Si su atacante puede interceptar la versión de texto sin formato del tráfico de red, entonces ver un hash de la contraseña es más seguro que ver la contraseña en texto sin formato. Aunque el atacante aún podría iniciar sesión en su servidor usando ese hash, necesitaría un crack de fuerza bruta (a veces precalculado) de ese hash para determinar la contraseña que podría ser útil en otros sistemas. Las personas deberían usar diferentes contraseñas en diferentes sistemas, pero a menudo no lo hacen.

Si un atacante obtuvo acceso a la base de datos, tal vez a través de una copia de una copia de seguridad, entonces querrá asegurarse de que uno no pueda iniciar sesión solo con ese conocimiento. Si, por ejemplo, almacenó un hash con el nombre de inicio de sesión comohash(login_name+password) , y pasó ese mismo hash del cliente para una comparación directa, entonces el atacante podría elegir un usuario al azar, enviar el hash leído de la base de datos e iniciar sesión como ese usuario sin conocer la contraseña, aumentando el alcance de la violación. En ese caso, enviar la contraseña en texto sin formato habría sido más seguro porque el atacante necesitaría conocer el texto sin formato para iniciar sesión, incluso teniendo una copia de la base de datos. Aquí es donde la implementación es clave. Ya sea que envíe una contraseña de texto sin formato o un hash del lado del cliente de esa contraseña, debe codificar ese valor en el lado del servidor y comparar ese hash con el hash almacenado en el registro del usuario.

Conceptos a tener en cuenta:

  • Usted "sal" un hash mezclando algún valor de alcance único con su hash, generalmente de fila única. Su propósito es garantizar la unicidad de los hash entre sí, incluso si los valores de texto sin formato que representan son los mismos, por lo que dos usuarios con la misma contraseña seguirían teniendo diferentes hash. No es necesario tratar una sal como un secreto.
  • Al autenticarse, siempre hash en el lado del servidor cualquier valor que pase del cliente como contraseña (incluso si ya está hash) y compárelo con un valor previamente hash almacenado en la base de datos. Esto puede requerir el almacenamiento de una versión con doble hash de la contraseña original.
  • Cuando haga un hash, considere agregar un salt exclusivo del servidor / clúster al hash, así como un salt exclusivo de la fila para evitar que coincidan los hash precalculados en las tablas de búsqueda.
phatfingers
fuente