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?
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?
Respuestas:
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).
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)
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.
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.
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 :)
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 ...
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.
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
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:
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.
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 password
campo. 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.
¿SSL / TLS no reemplaza al nonce? No veo valor agregado de esto ya que SSL / TLS también protege contra ataques de repetición.
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.
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: