
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 ) segundo o qual, em PHP, , só que é usado para fins . Qualquer senha a qualquer outra senha da lista. Isto é um truque diferente do de , basta reparar na diferença entre .
'0e1' == '00e2' == '0'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.
Usei o meu portátil, alguns loops for (ou foreach?), muitos ciclos de CPU e uma ventoinha externa em 2014, mas hoje pode/deve usar uma GPU e um hashcat modificado para isso. Consulte este artigo de Carl Löndahl e 0xb0bb.
Chick3nman e companhia também estão a trabalhar na sua versão do hashcat, fiquem atentos.
Se precisar de uma colisão real alfanumérica, aqui está uma colisão MD5 alfanumérica de 72 bytes com diferença de 1 byte, até 1 bit, por Marc Stevens:
md5("TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
=
md5("TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
Note que, se registar com a primeira senha e iniciar sessão com a segunda, isso pode ainda significar que o site usa bcrypt(md5($password)), e não apenas md5($password). Esse encapsulamento de hash é por vezes usado ao atualizar a hash de senhas, mas deve ser usado apenas temporariamente.
Consulte o Projeto HashClash do Marc se estiver interessado nestas colisões reais ou se quiser criar as suas próprias.
Colisões reais de hash LM por @solardiz (#35, obrigado!):
db82323cb0693862: 2275490 ou 0/*LUZ@44b3b60db75c15c1: 2716388 ou 1}DC<XT585e239d32df1998: 8351762 ou $;)5D|XConsulte o tweet para saber como gerar mais alguns.