¿Está utilizando HMAC para transmitir una contraseña?

8

Estoy escribiendo una pequeña aplicación web y no quiero transmitir las contraseñas de inicio de sesión como texto simple. Como no tengo SSL disponible, he escrito un sistema de desafío único que envía una cadena aleatoria con el formulario de inicio de sesión que luego se usa para hacer una contraseña usando HMAC-SHA256 en el lado del cliente. Uso la cadena de desafío aleatorio como mensaje y la contraseña del usuario como clave secreta para HMAC.

Sé que las soluciones de fabricación propia son generalmente una mala idea, así que quería preguntarme si estoy cometiendo un error aquí.

Editar : Parece que hay un malentendido, no estoy preguntando sobre el almacenamiento de contraseñas o los sistemas de desafío / respuesta, sino sobre la transmisión de HMAC y contraseñas. Para aclarar un poco: mi primera versión fue HMAC(msg=password, key=challenge) , porque pensé, bueno, el mensaje que quiero transmitir al servidor es la contraseña del usuario. Pero luego me di cuenta de que la cadena de desafío no es exactamente una clave secreta, así que la cambié, pero eso me hizo pensar si quizás hiciera algo totalmente incorrecto y pensé que era mejor preguntarlo.

    
pregunta Steffen 05.09.2011 - 10:03
fuente

4 respuestas

11

Además de ser un esquema auto-inventado, veo al menos los siguientes problemas con su propuesta:

  • No hay enlace con los datos reales. Cuando autentica a un usuario, no desea autenticar realmente "al usuario" solamente; desea autenticar una sesión , es decir, asegurarse de que lo que seguirá en el enlace será garantizado por ese usuario, y lo que enviará en el enlace será visto solo por el usuario previsto. Un atacante activo puede secuestrar la conexión, e incluso un intruso pasivo puede espiar cualquier cosa que envíes después.

  • El esquema es vulnerable a los ataques de diccionario sin conexión. Las contraseñas son débiles porque caben en cerebros humanos, y los cerebros humanos no son demasiado buenos para recordar contraseñas largas (y los usuarios humanos no tienen paciencia para escribir contraseñas largas). Es una batalla perdida: las computadoras regularmente ganan más poder, pero no los humanos. Probar las contraseñas potenciales tiende a ser un ataque exitoso, y observar su esquema produce suficiente información para probar las contraseñas (el atacante solo tiene que calcular un HMAC por contraseña y ver si coincide con lo que se observó). Dichos ataques pueden mitigarse en gran medida empleando un proceso de derivación lento (por ejemplo, bcrypt ) pero un solo HMAC no lo hará. bastar. Todavía es una mala idea incluso permitir un ataque de diccionario sin conexión.

  • El servidor tendrá que almacenar cierta información que es suficiente para que un usuario se autentique. Esto significa que un atacante que obtiene acceso de lectura temporal al almacenamiento del servidor (por ejemplo, un volcado de base de datos a través de alguna inyección de SQL) puede obtener contraseñas (o datos equivalentes a una contraseña) que le permiten hacerse pasar por usuarios a un costo muy bajo. Los mejores esquemas de contraseña almacenan en el servidor suficientes datos para verificar una contraseña, pero no más.

No es una tarea fácil crear un medio adecuado, seguro y autenticado para la transferencia de datos. Si realmente necesita volver a implementar algo usted mismo en lugar de usar alguna biblioteca SSL / TLS, entonces hágase un favor e implemente un protocolo estándar para eso, por ejemplo. SSL / TLS . Si tiene dudas sobre el certificado, considere TLS con SRP (no hay certificado en absoluto, autenticación mutua cliente-servidor basada en la contraseña, no es vulnerable a ataques de diccionario sin conexión).

Editar: acerca de su aclaración en su propia edición: usar los datos secretos (la contraseña) como clave en HMAC, y los datos conocidos públicamente (el desafío) como datos en HMAC, es teóricamente mucho mejor que lo contrario (HMAC fue diseñado para que la clave sea secreta); en la práctica, dada la estructura de HMAC, probablemente no cambiaría mucho la seguridad. Sin embargo, mis puntos expuestos anteriormente todavía se aplican.

    
respondido por el Thomas Pornin 05.09.2011 - 21:13
fuente
6

Hay al menos dos grandes inconvenientes con su esquema de desafío / respuesta:

  1. Tiene que almacenar contraseñas de texto sin formato (o equivalentes de texto sin formato) en el lado del servidor.

  2. Tiene que hacer el manejo de las contraseñas en el lado del cliente, lo que significa que no hay ninguna garantía de que el cliente esté ejecutando una parte de código "válida" para manejar la configuración de la contraseña. Por ejemplo, si se utilizó javascript para manejar la "cocción de contraseñas", no puede estar seguro de si el cliente está ejecutando un javascript malicioso, que (por ejemplo) envía la contraseña de texto sin formato directamente al atacante. Esto podría ocurrir por XSS, o quizás el atacante pudo modificar el tráfico HTTP antes de que llegue al cliente.

Como resultado, podría mejorar su esquema de desafío / respuesta. Eche un vistazo a enlace Esos algoritmos tratan el "problema de almacenamiento de contraseña de texto sin formato".

Pero incluso con esos "algoritmos mejorados de autenticación de desafío / respuesta", el segundo inconveniente permanece. Y no hay una forma portátil / confiable para manejarlo (excepto "SSL"). Posiblemente las extensiones del navegador podrían ayudar a reducir algunos problemas asociados con la operación de "cocción de contraseñas" basada en javascript (en el lado del cliente), pero no será tan buena como una conexión segura HTTPS.

    
respondido por el timoh 05.09.2011 - 14:21
fuente
3

La pregunta no especifica cuál es el modelo de amenaza contra el que se defiende, pero sospecho que el esquema que propone no será suficiente en la práctica. Mi sensación es que, en la práctica, en cualquier modelo de amenaza donde las contraseñas de texto simple son un problema, la propuesta de desafío-respuesta tampoco es adecuada.

En la práctica, en la mayoría de las situaciones en las que un atacante puede espiar sus comunicaciones, también puede manipular sus comunicaciones y montar un ataque de hombre en el medio. El ejemplo más destacado de esto es la comunicación a través de una red inalámbrica abierta, pero otros incluyen la falsificación de DNS, el malware del lado del cliente, los proxies HTTP maliciosos, etc. Y si el atacante puede montar un ataque de hombre en el medio, entonces el desafío La propuesta de respuesta no es segura: el atacante puede inyectar Javascript malicioso que roba la contraseña o hace otras cosas desagradables.

Por lo tanto, creo que la propuesta de desafío-respuesta proporciona un falso sentido de seguridad, ya que no autentica el contenido y el código servido por el servidor. Sospecho que, en lugar de implementar su solución, debería usar SSL / TLS (es decir, HTTPS): si tiene una necesidad donde las contraseñas de texto claro son problemáticas, es probable que necesite SSL / TLS.

    
respondido por el D.W. 05.09.2011 - 20:28
fuente
1

Para autenticar a un cliente, su enfoque suena casi correcto. Sin embargo, sí requiere que almacene la contraseña de texto sin formato en su servidor. Un pequeño ajuste a eso es almacenar algo derivado de la contraseña en lugar de la propia contraseña. Luego, en el lado del cliente, obtiene la misma información para alimentar en HMAC.

Sin embargo, ten mucho cuidado, ¡esto no es una autenticación mutua NO ! El cliente no autentica su sitio web y puede ser engañado / engañado para que proporcione su contraseña.

¿Y has pensado en repetir el ataque?

¿Qué hay del ataque de fuerza bruta fuera de línea?

Lo que estoy haciendo es poner un fuerte énfasis en la primera parte de tu última oración.

    
respondido por el Nam Nguyen 05.09.2011 - 14:49
fuente

Lea otras preguntas en las etiquetas