¿Es seguro el siguiente esquema de autenticación?

7

Estaba tratando de diseñar un sistema de autenticación que hiciera que sea mucho más difícil adivinar una contraseña a través de la fuerza bruta, y reducir el riesgo para un usuario si la contraseña de hash fue robada a través de un ataque basado en espionaje. Además, dado que el código del lado de mi cliente será fácilmente visible para aquellos que deseen verlo (está en un lenguaje interpretado, sin embargo, sí cifro y ofusco al cliente distribuido), quería poder evitar que un atacante mirara La fuente para hacerse pasar por un usuario fácilmente. La seguridad a través de la oscuridad es la seguridad NO .

Aquí está el algoritmo que pensé. Quería someterlo a examen público porque los algoritmos de criptografía siempre funcionan mejor cuando están sujetos a tantas opiniones como sea posible, IMHO.

(Todos los hashes se calculan con el SHA-2 y un tamaño de bloque de 512 bits. No se sabe que este algoritmo sea vulnerable a cualquier ataque de colisión o pre-imagen, y es una función de hash criptográfica segura.)

[LADO DEL CLIENTE]

  1. El usuario proporciona un nombre de usuario de cualquier carácter / símbolo / número con menos de 30 caracteres y una contraseña de cualquier carácter / símbolo / número que tenga entre 8 y 200 caracteres de longitud.

  2. El nombre de usuario está hasheado.

  3. El hash del nombre de usuario se agrega al final de la contraseña del usuario como una sal.

  4. La contraseña con sal está en hash, y luego ese hash está en hash.

  5. La fecha y la hora actuales se solicitan al servidor de autenticación y, a continuación, se recortan.

  6. El hash de la marca de tiempo se agrega al hash de nombre de usuario / contraseña como lo que llamaré 'sal dependiente del tiempo'. Esta última combinación se procesa para generar el hash de autenticación final.

  7. El nombre de usuario, el hash con marca de tiempo, la contraseña con sal y el tiempo utilizado para generar el sal dependiente del tiempo se envían al servidor a través de una conexión TLS / SSL.

[LADO DEL SERVIDOR]

  1. El servidor verifica que la marca de tiempo recibida está en el último minuto. Si no es así, el servidor indicará que la autenticación falló.

  2. El servidor hace un hash del nombre de usuario / contraseña con sal y compara eso con la base de datos almacenada con sal / hash de contraseña. Si no coinciden la autenticación falla. (Para aclarar, el servidor tiene un hash de hash de contraseña con sal. Verifica que contra un hash del hash de contraseña con sal dado por el cliente).

  3. El servidor calcula un hash de la marca de tiempo enviada por el cliente.

  4. El servidor separa el hash de marca de tiempo generado y el hash de contraseña con sal para formar el hash de autenticación.

  5. Compara el hash de autenticación que produjo con el hash de autenticación enviado por el cliente. Si son iguales, se reporta autenticación. De lo contrario, informa de un error de autenticación.

Si estoy en lo cierto, creo que este esquema de autenticación hace que el hecho de forzar una contraseña bruta sea casi imposible, y hace que una contraseña robada a través de espionaje solo sea útil por un minuto entero.

Sin embargo, contra lo que no protege, ya que creo que es imposible, son las contraseñas robadas al usuario cuando se ingresan en el cliente. Spyware podría robar el nombre de usuario y la contraseña reales.

EDIT 1 :: Se corrigió el proceso de autenticación para que el servidor no almacene el hash de contraseña con sal, solo un hash de ese valor. Esto evita que un atacante con acceso a la base de datos sepa la contraseña original. La razón por la que se debe hacer esto es el valor de hash del hash de contraseña con sal. es la contraseña desde el punto de vista del servidor. Almacenar el hash de contraseña con sal en la base de datos sería lo mismo que almacenar las contraseñas de todos los usuarios en texto sin formato.

EDIT 2 : se corrigió el esquema para que la autenticación dependiera de la hora del servidor, no del cliente.

EDITAR 3 : hizo que la longitud de la contraseña fuera menos restrictiva, pero la mantuvo razonable.

    
pregunta Josh 02.08.2011 - 14:02
fuente

8 respuestas

9

Si pasa por SSL / TLS, lo que garantiza la autenticación del servidor (el cliente está seguro de que está hablando con el servidor correcto) y la confidencialidad e integridad de los datos transmitidos, entonces no hay nada que temer, o más bien , si se produce una indagación, debe estar justo en el cliente o en el servidor, momento en el que tiene problemas más graves (si un atacante puede leer los datos enviados directamente en el cliente, entonces probablemente también pueda registrar las pulsaciones de teclado).

Si consideramos su esquema de hashing de contraseña por sí mismo (es decir, sin tener en cuenta SSL / TLS), entonces tiene algunos problemas:

  • Incluyes tu "sal" simplemente agregándola. No hay pruebas de que esto no cause problemas con SHA-512. SHA-512 es una función hash de Merkle-Damgård , lo que significa que es un poco menos que ideal; tiene alguna estructura (por ejemplo, el "ataque de extensión de longitud"). Esto no significa que SHA-512 esté roto; solo que lo manejas como si fuera un Random Oracle mientras que es "solo" resistente a las colisiones y preimágenes.
  • No se repiten suficientes invocaciones de la función hash. Esto hace que el proceso sea demasiado rápido: un atacante que observe el hash resultante puede "probar" las contraseñas potenciales y podrá hacerlo a alta velocidad (millones de contraseñas por segundo, con una PC simple). Esto se denomina "ataque de diccionario" y tiende a funcionar porque los usuarios son malos para elegir y recordar buenas contraseñas.
  • Utiliza SHA-512 en lugar de SHA-256. Habla de un "lenguaje interpretado": si ese es Javascript, entonces ese lenguaje es muy ineficiente con las operaciones de 64 bits (SHA-512 está lleno de ellas), por lo que usar SHA-512 en lugar de SHA-256 limita severamente el número de iteraciones que podría realizar en el sistema cliente; esto aumenta de manera correspondiente la eficiencia del ataque de diccionario.

Las recomendaciones habituales para el hashing de contraseñas son PBKDF2 , bcrypt y scrypt (mi favorito personal es bcrypt; PBKDF2 no fue diseñado inicialmente para eso , y scrypt todavía es demasiado nuevo para ser de confianza general.

Hay protocolos de autenticación que, por diseño, son inmunes a los ataques de diccionario sin conexión: se denominan Intercambio de claves autenticado por contraseña . Los protocolos PAKE permiten la autenticación mutua basada en contraseña entre el cliente y el servidor, de tal manera que un atacante o incluso un atacante que se hace pasar por el cliente o el servidor, no puede aprender nada que le permita "probar contraseñas" por su cuenta. sistemas El atacante está restringido a ataques de diccionario en línea : cada adivinación de contraseña implica la interacción con el cliente o el servidor. El protocolo PAKE más conocido es SRP que se ha integrado en SSL / TLS . Con TLS + SRP, obtiene un túnel de datos seguro en el que el servidor y el cliente se autentican mutuamente con respecto a la contraseña, sin ningún certificado (esa es la parte más brillante de la misma). Como beneficio adicional, el servidor no necesita almacenar la contraseña en texto no cifrado, solo un valor derivado de ella (como si estuviera bloqueado), por lo que un atacante que descargue la base de datos del servidor no aprende las contraseñas (sí aprende lo suficiente para realizar una Sin embargo, el ataque del diccionario sin conexión). GnuTLS es una biblioteca que implementa SSL / TLS con soporte SRP.

    
respondido por el Thomas Pornin 02.08.2011 - 19:32
fuente
9

De un vistazo, esto parece que cualquier persona que obtenga su tabla de contraseñas puede iniciar sesión como usuario. Simplemente omite los pasos del cliente 1-4 y sustituye el hash que obtuvo de la db. Entonces, tu esquema es muy débil en este escenario.

¿Por qué no usas hashing de contraseña estándar? La mayoría de los ataques de intercepción ya se evitan si utiliza SSL / TLS y valida la huella digital del servidor en una lista blanca.

O si estás paranoico usa una buena implementación de SRP . Pero no lo implemente. Es muy fácil producir una mala implementación que parece funcionar pero es insegura.

    
respondido por el CodesInChaos 02.08.2011 - 16:00
fuente
5

No veo lo que estás tratando de lograr con este esquema, que no se puede hacer con un método ya conocido y comprobado.

Primero que nada, no puedes depender de la hora del cliente. Muchas personas no sincronizan su reloj, y tendrías que tener en cuenta las zonas horarias.

En segundo lugar, el atacante puede pasar por el esquema de autenticación tantas veces como le plazca a la fuerza bruta como se indica. Podría agregar funcionalidad de bloqueo, pero puede agregarla a cualquier esquema.

Tercero, su esquema evita la repetición de la POST de autenticación, pero el uso del tiempo, lo cual es una mala idea debido a los problemas de sincronización. Una mejor idea sería el desafío-respuesta, un mecanismo ampliamente aceptado para garantizar la frescura.

Si incluyes un token de desafío en el hash, un hash interceptado ni siquiera proporcionará acceso por un minuto: solo podría usarse una vez.

Le recomiendo que implemente autenticación de dos factores si está preocupado por la autenticación y no quiere confiar en SSL. Puede usar la respuesta de desafío en combinación con hashes salados y estirados para evitar la repetición y el craqueo fuera de línea.

    
respondido por el chris 02.08.2011 - 18:19
fuente
5

Tendré que unirme a aquellos que dicen "deja de intentar diseñar tu propio sistema de cifrado". No eres lo suficientemente inteligente. No soy lo suficientemente inteligente. Si no ha pasado una década trabajando en el problema, no puede hacerlo.

¿Por qué tienen longitudes máximas? De todas formas siempre lo vas a juntar. Permítales tener una contraseña de un millón de caracteres si lo desean, no va a importar, porque solo almacena los 32 bytes del hash final, no los millones de bytes de la contraseña.

A algunas personas les gustan las frases de paso, que pueden ser una oración larga de 100 caracteres. Puedo escribir una contraseña de 100 caracteres usando una frase más rápido que una contraseña complicada con caracteres especiales.

No bases la sal en el nombre de usuario. Utilice información completamente aleatoria y genere una nueva sal cada vez que el usuario cambie su contraseña. De lo contrario, un pirata informático podría calcular un gran diccionario para un usuario y piratear repetidamente la cuenta incluso cuando el usuario cambia la contraseña.

Parece que piensas en términos de elegir la función hash más segura posible. La realidad es que SHA-512 no será más seguro que el MD5 en tales aplicaciones, especialmente si usa el fortalecimiento de teclas. Repetir el MD5 mil veces es mucho más seguro que el SHA-512. La seguridad es un compromiso: elija el algoritmo hash que se realiza más fácilmente en el cliente, que probablemente sea SHA-1 o SHA-256, no el "más seguro" posible.

SSL ya tiene protección de reproducción. ¿Por qué complicar su sistema de autenticación haciendo su propio? Aunque, debido a SSL, tiene la garantía de que los relojes no están demasiado lejos (de lo contrario, SSL fallaría).

Incluso si hace todo mal, como usar un simple hash MD5, los piratas no podrán descifrar más del 50% de las contraseñas de su sitio. Por el contrario, si haces todo bien, los hackers aún podrán descifrar el 20% de las contraseñas a través de un diccionario ligeramente mutado. No importa lo que haga, no puede evitar que se descifren algunas contraseñas si la base de datos está en peligro. En su lugar, su objetivo debería ser hacer las cosas estándar para minimizar los ataques, como el PBKDF2 con sales y el fortalecimiento de claves.

Además, no importa cuánto tiempo dedique a esto, es probable que cometa otros errores comunes, como enviar cookies de sesión en texto simple.

En última instancia, lo que trato de decir es: deja de intentar diseñar tu propio sistema criptográfico. Repite el estúpido meme "la oscuridad no es seguridad" sin entenderlo realmente, pero se niega a seguir el consejo común de no intentar diseñar su propio sistema de cifrado.

    
respondido por el Robert David Graham 03.08.2011 - 20:20
fuente
3

No veo cómo esto haría que la fuerza bruta sea más difícil desde el lado del cliente. Podría simplemente automatizar pasar su aplicación una lista de nombre de usuario / contraseñas hasta que una funcione. Si obtuviera acceso a su base de datos, las contraseñas forzadas con tablas de arco iris serían casi imposibles (si eso es lo que quiere decir con lo que quiere protegerse). Pero aún tendrá que almacenar el salt con el nombre de usuario + contraseña de hash (y presumiblemente podría aplicar ingeniería inversa a su esquema de hash), por lo que podría generar una tabla de arco iris para una entrada en su base de datos, si estuviera apuntando a un usuario específico, o Solo quería una cuenta.

En cuanto a la prevención de forzados brutos en el lado del cliente, podría poner un bloqueo de tiempo en su inicio de sesión después de un intento fallido. Después de cada intento fallido, el usuario tiene que esperar 2 ^ (intentos fallidos) segundos, antes de poder intentar otro inicio de sesión. Esto tendría que ser ejecutado del lado del cliente y del servidor. También asegúrese de pensar en cómo un usuario malintencionado podría usar su esquema como DoS para otro usuario.

    
respondido por el Petey B 02.08.2011 - 15:25
fuente
2

No lo veo mencionado en ningún otro lugar, así que lo mencionaré aquí: Tu sal no es particularmente segura. El (único) punto de una sal es hacer que los ataques de precomputación como las tablas del arco iris sean poco prácticos, y esto se logra de manera más efectiva si no hay forma de adivinar la sal, y tiene una amplia gama de valores posibles.

Al usar el nombre de usuario, se asegura de que la misma combinación de usuario y contraseña siempre tendrá el mismo hash. Debido a que hay un conjunto limitado de nombres de usuario comunes, un atacante aún puede calcular previamente los hashes para esos nombres de usuario. Ha multiplicado el esfuerzo requerido por el número de nombres de usuario comunes, pero eso no es intratable. El uso de una sal aleatoria, como es la práctica estándar, introduce un multiplicador mucho más grande.

Finalmente, agregaré un complemento adicional para la brigada "no inventes tus propios criptosistemas". Ya existen sistemas bien probados que hacen lo que usted está tratando de hacer, como lo ilustra la excelente respuesta de Thomas. Usa uno de ellos, no inventes el tuyo.

    
respondido por el Nick Johnson 03.08.2011 - 03:56
fuente
1

Parece que has perdido el punto de hash de una contraseña. El punto de hashing de una contraseña es el siguiente:

1) El servidor solo almacena la contraseña con hash.

2) El usuario debe proporcionar al servidor la contraseña no lavada.

3) Por lo tanto, alguien que roba la base de datos de contraseñas del servidor todavía no sabe qué dar al servidor a menos que brute obligue a la contraseña.

Has hecho esto:

1) El servidor solo almacena la contraseña con hash.

2) El usuario proporciona al servidor la contraseña con hash.

3) Por lo tanto, alguien que roba la base de datos de contraseñas del servidor puede hacerse pasar por cualquier usuario sin importar cuán buena sea su contraseña.

A los efectos de evaluar el algoritmo servidor-cliente, la "contraseña" es la información mínima necesaria para la autenticación exitosa en el servidor. En el caso de su algoritmo, la "contraseña" es, por lo tanto, el hash del hash creado en el paso 4, y eso es precisamente lo que está almacenado en el servidor. Por lo tanto, estás almacenando contraseñas no rotas / sin cifrar. Eso no es bueno.

    
respondido por el David Schwartz 30.08.2011 - 15:56
fuente
0

La fuerza bruta parece casi imposible de hecho, la forma más rápida de solucionar el problema es un tcp sniffer para mostrar los datos enviados al servidor (nombre de usuario, contraseña y fecha y hora) y usarlos en una nueva solicitud al servidor.

Si su servidor comprueba la marca de datos del cliente para verificar si no es "anterior", entonces 1 minuto, Su cliente deberá autenticarse cada minuto. Un detector de tcp todavía se puede usar para detectar esto.

Para evitar esto, SSL podría ser una solución.

    
respondido por el Thomas 02.08.2011 - 14:10
fuente

Lea otras preguntas en las etiquetas