
Magic hashes – "colisões" de hash do PHP
Registe-se com senha 1 e depois inicie sessão com senha 2. Se conseguir entrar, então o armazenamento usa o algoritmo especificado para aplicar hash à senha e o PHP usa == para as comparar (para MD5, SHA-1 e texto simples).
Para MD5, SHA-1 e a família SHA-2, usa-se o truque há muito conhecido (na verdade é uma funcionalidade documentada, consulte tabelas de comparação de tipos do PHP e números de ponto flutuante) segundo o qual, em PHP, '0e1' == '00e2' == '0', só que é usado para fins práticos. Qualquer senha corresponde a qualquer outra senha da lista. Isto é um truque diferente do de strings integrais a transbordar para números de ponto flutuante, basta reparar na diferença entre estas duas linhas.
Estes são todos os algoritmos com hashes mágicos:
md5(md5(password))Citando @0xb0bb, "existem outras aplicações para hashes mágicos além da comparação de senhas (como camadas de cache ou dados derivados da saída de uma função hash) onde estes algoritmos conhecidos como inseguros, menos conhecidos e pseudo-hash podem ser encontrados mais facilmente."
Para texto simples, são usados vários truques de conversão. A primeira senha corresponde apenas à segunda. Os truques estão agrupados por versões do PHP que os permitem.
O bcrypt trunca senhas até um comprimento máximo de 72 caracteres. As senhas correspondem se os primeiros 72 caracteres de ambas as senhas coincidirem.
O descrypt (crypt DES UNIX tradicional) trunca senhas até um comprimento máximo de 8 caracteres. As senhas também correspondem se os primeiros 8 caracteres de ambas as senhas coincidirem, consulte a secção "Verificação cruzada geral".
Se usar uma senha com mais de 64 bytes e aplicar hash com PBKDF2-HMAC-SHA1, ela é primeiro submetida a um pré-hash com SHA1, portanto PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2) porque sha1(password1) === bin2hex(password2). O pré-hash semelhante é aplicado no caso de PBKDF2-HMAC-SHA224 e PBKDF2-HMAC-SHA256.
Neste momento há apenas um hash mágico em cada um graças a Norbert Tihanyi, esperemos que mais sejam adicionados no futuro.
Use === ao comparar qualquer coisa* em PHP, não ==. E use password_hash() e password_verify() para hash de senhas em PHP; não use MD5 ou SHA-1. *Use hash_equals() ao comparar hashes.
Tudo começou com este tweet. Gerei QNKCDZO e 240610708 em fevereiro de 2014 e desde então espalhou-se por toda a internet. Basta pesquisar no Google.