¿Cuándo y dónde tengo una contraseña?

3

Digamos que tengo un cliente y un servidor. Quiero que el usuario con el cliente inicie sesión en el servidor con una combinación de nombre de usuario y contraseña.

Para iniciar sesión, tienen que ingresar la contraseña correcta que (cuando se trata de un hash) coincide con los detalles almacenados en mi servidor.

¿Dónde realizo la función de hashing en la contraseña ingresada por el usuario? ¿Debería la computadora del cliente realizar la función de hash y enviar el resultado a mi servidor (con la esperanza de que nadie resuelva un hash funcional para enviar)? O, ¿debería el servidor realizar el hash en la contraseña (esperando que la conexión entre los dos sea segura)?

Mantengo esto lo más abstracto posible con la esperanza de aplicarlo a múltiples situaciones.

    
pregunta Erikster 25.03.2014 - 15:52
fuente

4 respuestas

2

Piensa en el propósito del hash.

Si alguien ingresa en su base de datos, no encontrará las contraseñas, sino solo los hashes que deben ser forzados en las contraseñas para que sean útiles.

Al permitir que el cliente envíe un hash en lugar de la contraseña, usted crea efectivamente la nueva contraseña y todos los beneficios se pierden. es decir, si alguien ingresa a la base de datos, puede ingresar instantáneamente a todas las cuentas con los datos que encuentre allí.

Por lo tanto, el cliente siempre debe enviar la contraseña y el servidor debe hacer el hashing.

    
respondido por el user2675345 25.03.2014 - 15:57
fuente
6

Idealmente , deberíamos hacer la mayoría (¡pero no todas!) del hashing en el lado del cliente.

La necesidad general de hashing de contraseña, con todas las iteraciones y sales involucradas (consulte esta respuesta ), es asegurarse de que el valor almacenado (el" token de verificación de contraseña ") no se pueda usar fácilmente para un ataque de diccionario sin conexión (el atacante intenta una contraseña potencial, hasta que coincida con el se encuentra el valor almacenado). Para que se cumpla la funcionalidad específica de , basta con que el hashing de contraseña lento y con sal se produzca "en algún lugar", y la máquina cliente es un lugar razonable para eso.

Sin embargo, la protección contra ataques de diccionario fuera de línea es solo una parte del objetivo de seguridad. En particular, no queremos que un atacante pueda obtener valores "equivalentes a una contraseña". Si realiza el hashing completo del lado del cliente y almacena el valor "tal como está" en el servidor, un vistazo a la base de datos del servidor (como sucede con demasiada frecuencia con las inyecciones de SQL y las cintas de copia de seguridad perdidas) revelará los valores de hash y permitirá El atacante para iniciar sesión como cualquier usuario inmediatamente. Por lo tanto, aún desea hacer algunos del lado del servidor hash.

Lo que funciona, por ejemplo, es tener el hash lento y salado en el cliente, que resulta en un valor V , y el servidor almacena SHA-256 ( V ). Dado que se ha realizado el hash lento y salado, la protección contra los ataques de diccionario está ahí; y dado que el servidor no almacena V pero aún requiere que el cliente envíe a V para que se le otorgue acceso, las infracciones de solo lectura no se elevan de manera trivial al compromiso total de lectura-escritura.

El hashing del lado del cliente tiene la característica muy interesante de usar recursos del lado del cliente, no del lado del servidor, lo que permite que un servidor determinado procese muchos clientes simultáneos sin quedarse sin CPU, mientras sigue teniendo Un hashing de contraseña lento y salado en general. Sin embargo, esto no se hace a menudo en la práctica debido a algunos inconvenientes:

  • El cliente no puede hacer hash sin conocer la sal, que está almacenada en el servidor. Por lo tanto, el protocolo implica un viaje de ida y vuelta adicional: el cliente debe enviar el nombre de usuario, el servidor responde con el salt y luego (solo entonces) el cliente puede hacer el hash lento y salado.

  • Los clientes son heterogéneos: algunos pueden ser bastante débiles, lo que implica un límite estricto en el número de iteraciones que se pueden aplicar (porque un teléfono inteligente lento como cliente no significa que el usuario humano sea más paciente). Esto es especialmente cierto para los clientes basados en la Web, porque los cálculos de Javascript son muy lentos (en comparación con el código nativo o incluso los applets de Java o Silverlight).

  • El hashing del lado del cliente significa código del lado del cliente, que puede no ser fácilmente actualizado o modificado. Con el hash del lado del servidor, la elección de la función de hash depende completamente del servidor y se puede cambiar sin tener que alterar los clientes instalados de ninguna manera.

  • A algunos servidores les gusta tener acceso a contraseñas de texto simple de vez en cuando, no para el almacenamiento, sino para otras funciones como la detección automática de contraseñas de usuario muy deficientes o el envío de una copia de las contraseñas a las autoridades pertinentes de aplicación de la ley (cuando corresponda). - No estoy diciendo que esto sea bueno o malo , pero cuando se aplica, no está sujeto a una elección por parte de quien diseñe el sistema de inicio de sesión; si está en un país en el que debe permitir que las agencias gubernamentales revisen las contraseñas, entonces, bueno, debe hacerlo, por lo que esto se convierte en un elemento del contexto a tratar).

respondido por el Thomas Pornin 25.03.2014 - 17:07
fuente
3

Las contraseñas deben estar marcadas con hash al menos una vez en el servidor, para evitar ataques de estilo hash en el que un atacante malintencionado puede simplemente inyectar el hash que olfateó de la red para autenticarse. Sin embargo, esto no significa que no debas hash la contraseña localmente. Una estrategia bastante paranoica es hacer que el usuario envíe un hash iterado de una contraseña, utilizando una gran cantidad de iteraciones, por ejemplo, 10,000, que luego almacena.

Cuando el usuario quiere autenticarse, ingresa la misma contraseña, pero solo hash 9999 veces. Luego, el servidor localmente hashsea la contraseña de 9999 veces hash una vez, y si coincide con la contraseña de 10,000 hash almacenada, el servidor reemplaza el hash almacenado con el hash iterado 9999 veces. En cada intento subsiguiente, el usuario itera el hash una vez menos, y si se autentica con éxito, el servidor reemplaza el hash antiguo con el hash nuevo.

El usuario se ve obligado a restablecer su contraseña cuando el número de iteraciones disminuye. Se pueden usar varias tácticas para incorporar sales en varios puntos para agregar seguridad adicional. El servidor también debe contener el número de iteraciones que espera que el cliente haya enviado para que el cliente (o varios clientes) pueda mantenerse sincronizado.

En resumen, siempre hash la contraseña en el servidor, pero eso no impide que también puedas hash localmente, lo que también puede evitar que el servidor sepa la contraseña del usuario, aunque sea brevemente.

    
respondido por el jhoyla 25.03.2014 - 16:14
fuente
0
  

¿Debería la computadora del cliente realizar la función de hash y enviar el resultado de hash a mi servidor (esperando que nadie resuelva un hash funcional para enviar)?

Si usa Firefox, le sugiero que descargue una pequeña herramienta llamada "TamperData". Enciéndalo y vea qué tipo de estragos puede causar si se sienta entre el cliente y el servidor.

Entonces la respuesta a esta pregunta es: NO. La mejor manera de manejar esto es almacenar un hash salado en su base de datos y su aplicación de servidor trata a todos los datos entrantes como maliciosos. En tu caso, ¿cómo implementarías el hash del cliente? ¿En Javascript? Para verificar el hash, el código del servidor y del cliente debe estar en bloqueo, y como el atacante tiene acceso total a su algoritmo de hash de Javascript ... realmente ha hecho pública una gran cantidad de información de implementación, como por ejemplo el hash estás usando, también tendrías que regalar tu sal, demasiado para confiar al azar. Mejor que sus páginas sean simples y tontas, y deje la validación para la aplicación del servidor. La usabilidad puede requerir alguna validación del lado del cliente, solo tenga cuidado aquí porque, de nuevo, está regalando detalles de implementación a sus posibles atacantes.

En resumen:

  1. Suponga que toda la fuente (cliente / servidor / base de datos) es pública y está disponible gratuitamente. Un punto secundario aquí es también recordar que la inclusión de bibliotecas de Javascript en sus páginas lo abre para atacar. Es mejor tener copias locales en su organización que hayan sido examinadas profesionalmente. ¡Cuidado con los servicios web también! ¡Solo porque una fortuna 500 expone un servicio web no significa que un atacante no pueda aprovechar su entrada / salida contra usted!

  2. Encuentre sus límites: en aplicaciones MVC como aplicaciones web, esto es bastante fácil. Todo lo que provenga del usuario se considerará hostil hasta que se valide.

respondido por el avgvstvs 25.03.2014 - 16:30
fuente

Lea otras preguntas en las etiquetas