Si md5 solo es inseguro debido a su velocidad, ¿por qué esta solución no lo hace razonablemente seguro?

-1

Voy a prefaciar esto diciendo que no tengo absolutamente ninguna pista cuando se trata de criptografía, pero estoy publicando esta pregunta porque estoy muy interesado y no tengo dudas de que hay algunas personas inteligentes aquí que lo harán. Sé capaz de explicarme esto como si tuviera 5.

Por lo que entiendo, md5 se considera inseguro debido a la rapidez con la que se pueden hacer hash, lo que significa que los ataques de fuerza bruta son muy fáciles y los atacantes incluso podrían comparar una contraseña de hash md5 con una tabla generada previamente.

Es por eso que cuando (usando php) calculo md5("password"); y me da 5f4dcc3b5aa765d61d8327deb882cf99 puedo conectar ese valor a un sitio como esto y en 45 ms repite 5f4dcc3b5aa765d61d8327deb882cf99 MD5 : password

¿Pero qué pasa si agrego algunos datos "de ayuda" al principio y al final de mi contraseña?

<?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    echo md5($helper."password".$helper);
?>

Devuelve 9f1f60fc8d76caa77b11810a0d68e0c5 (que el mismo sitio no puede descifrar, aunque no estoy seguro de que las tablas del arco iris puedan, parece poco probable, ¿no?) que luego podría almacenar, junto con el "ayudante" para compararlas con futura contraseña enviada por correo:

<?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    $accepted = "9f1f60fc8d76caa77b11810a0d68e0c5";

    $pass = $_POST["password"];

    if (md5($helper.$pass.$helper)==$accepted) {
        echo "Password was correct.";
    } else {
        echo "Password was incorrect.";
    }
?>

¿Qué hay de malo en este enfoque? Estoy seguro de que hay alguna razón por la que no es una buena idea, simplemente no entiendo cómo funciona md5 y la criptografía en general para señalar por qué.

    
pregunta John Michael Dorian 08.06.2014 - 19:54
fuente

2 respuestas

3

La cadena de ayuda no ayuda.

Si es público, entonces es solo un prefijo constante que el atacante debe agregar a cada contraseña. Básicamente, ha creado una ligera modificación de MD5 con los mismos problemas que el MD5 real. Esto no hace nada para detener los ataques de fuerza bruta e incluso puede introducir debilidades sutiles.

Sí, un atacante no podría usar una tabla de búsqueda MD5 estándar. Pero dada la potencia de cálculo del hardware actual, en primer lugar no hay necesidad de tablas de búsqueda: incluso una GPU de jugador antigua como la HD 6990 puede calcular 10 mil millones de hashes por segundo . Y el hardware especializado como un ASIC tiene un rendimiento mucho mejor. No pude encontrar cifras concretas para MD5, pero actualmente puedes obtener 200 mil millones de hashes SHA-256 por segundo con hardware por solo $ 500.

Si la cadena auxiliar es secreta, entonces la seguridad de la contraseña completa depende de este secreto. Tan pronto como se conoce la cadena, el atacante puede volver a intentar miles de millones de posibles contraseñas por segundo.

Sí, esto es algo mejor que el MD5 simple, pero introduce un punto único de falla innecesario. La razón principal por la que las contraseñas de hash en lugar de cifrarlas es porque no queremos ningún acceso directo para un atacante. Incluso si el atacante sabe todo acerca de su sistema, los hashes deberían ser tan seguros como lo eran antes. Obviamente, este no es el caso en su esquema.

De cualquier manera, esto no es una mejora real.

Sin embargo, la idea de agregar cadenas aleatorias a la contraseña conduce a un concepto válido: los algoritmos hash de contraseña especializados como bcrypt tienen un parámetro adicional para una llamada "sal". Una sal es una cadena aleatoria única que se genera por contraseña y se mezcla en el procedimiento de hashing. Esto obliga a un atacante a romper cada hash individualmente, porque cada hash se calculó básicamente con una variación única del algoritmo principal.

Sin embargo, solo salado no es suficiente. El requisito más importante para un algoritmo de hash de contraseña es que debe ser computacionalmente costoso. Calcular un hash debería usar muchos recursos. En lugar de miles de millones de hashes por segundo en el hardware de stock, solo queremos unos hashes por segundo. Esto hace poca diferencia para los usuarios legítimos, pero es un problema enorme si está intentando un ataque de fuerza bruta.

    
respondido por el Fleche 08.06.2014 - 21:40
fuente
0

Hay mucho mal con tu enfoque.

  1. PVD en la fuente . Si hay un problema con su código fuente o aparece un mensaje de error, su código fuente podría revelar el valor de $accepted . Esto permitiría a un atacante usar el hash que descubrieron para atacarlo sin conexión. Podrían usar una computadora extremadamente poderosa y utilizar miles de millones de posibilidades de contraseña con una latencia de 0.
  2. md5 . Se han encontrado colisiones para md5. Esto significa que carece de las características de una función criptográfica hash.
  3. Sin limitación . Tienes razón acerca de la velocidad. Podría escribir un script que publique constantemente su servidor y su código no hace nada para ralentizarlos. Sin tiempo de espera, etc.
  4. Tu código no protege nada . Sé que su código es solo un ejemplo, pero para futuros lectores este código PHP que NO desea copiar y pegar. Después de la rama if else, tanto los usuarios autenticados como los no autenticados vuelven a la misma ruta de ejecución. Es casi seguro que será mejor hacer esto

    <?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    $accepted = "9f1f60fc8d76caa77b11810a0d68e0c5";
    
    $pass = $_POST["password"];
    
    if (md5($helper.$pass.$helper)==$accepted) {
        echo "Password was correct.";
    } else {
        echo "Password was incorrect.";
        exit(0);
    }
    ?>
    

Lo que quieres hacer es usar una función más fuerte que también sea más lenta. En php es muy fácil usar la función crypt() , que implementa bcrypt (lo cual es bastante bueno, pero hay otros KDF que también funcionan como scrypt). Aquí hay un ejemplo que tomé directamente de los documentos php. Este también es un código incorrecto, pero ilustra cómo usar la entrada del usuario para verificar una contraseña.

<?php
    $hashed_password = crypt('mypassword');

    /* You should pass the entire results of crypt() as the salt for comparing a
    password, to avoid problems when different hashing algorithms are used. (As
    it says above, standard DES-based password hashing uses a 2-character salt,
    but MD5-based hashing uses 12.) */
    if (crypt($user_input, $hashed_password) == $hashed_password) {
        echo "Password verified!";
    }
?>

Es bueno tener en cuenta que las funciones como SHA, md5 y otros algoritmos de hashing conocidos fueron diseñados para ser rápidos. ¡Las funciones rápidas son lo que a los atacantes les gusta ver!

    
respondido por el user11869 08.06.2014 - 20:24
fuente

Lea otras preguntas en las etiquetas