
Hashes mágicos – "colisiones" de hash de PHP
Regístrate con contraseña 1 y luego inicia sesión con contraseña 2. Si consigues entrar, entonces el almacenamiento usa el algoritmo especificado para aplicar hash a la contraseña y PHP usa == para compararlas (para MD5, SHA-1 y texto plano).
Para MD5, SHA-1 y la familia SHA-2 se usa el truco conocido desde hace tiempo (en realidad es una funcionalidad documentada; consulta tablas de comparación de tipos de PHP y números de coma flotante) según el cual en PHP '0e1' == '00e2' == '0'; aquí solo se usa con fines prácticos. Cualquier contraseña coincide con cualquier otra contraseña de la lista. Este es un truco distinto al de las cadenas integrales que se desbordan en números de coma flotante; basta con ver la diferencia entre estas dos líneas.
Estos son todos los algoritmos con hashes mágicos:
md5(md5(password))En palabras de @0xb0bb, «hay otras aplicaciones para los hashes mágicos además de la comparación de contraseñas (como capas de caché o datos derivados de la salida de una función hash) en las que estos algoritmos conocidos por ser inseguros, menos conocidos y pseudo-hash se pueden encontrar con mayor facilidad».
Para texto plano se usan varios trucos de conversión. La primera contraseña coincidirá únicamente con la segunda. Los trucos están agrupados por versiones de PHP que los permiten.
bcrypt trunca las contraseñas a una longitud máxima de 72 caracteres. Las contraseñas coinciden si los primeros 72 caracteres de ambas contraseñas coinciden.
descrypt (crypt DES tradicional de UNIX) trunca las contraseñas a una longitud máxima de 8 caracteres. Las contraseñas también coinciden si los primeros 8 caracteres de ambas contraseñas coinciden; consulta la sección «General cross-check».
Si usas una contraseña de más de 64 bytes y le aplicas hash con PBKDF2-HMAC-SHA1, primero se pre-hashea con SHA1, de modo que PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2) porque sha1(password1) === bin2hex(password2). El mismo pre-hasheo se aplica en el caso de PBKDF2-HMAC-SHA224 y PBKDF2-HMAC-SHA256.
Por ahora solo hay un hash mágico en cada uno de ellos, gracias a Norbert Tihanyi; con suerte, se añadirán más en el futuro.
Usa === al comparar cualquier cosa* en PHP, no ==. Y usa password_hash() y password_verify() para el hash de contraseñas en PHP; no uses MD5 ni SHA-1. *Usa hash_equals() al comparar hashes.
Todo empezó con este tweet. Generé QNKCDZO y 240610708 en febrero de 2014 y desde entonces se ha extendido por todo internet. Solo búscalo en Google.