
Hash magici – "collisioni" di hash PHP
Registrati con password 1 e poi accedi con password 2. Se riesci ad accedere, l'archiviazione usa l'algoritmo specificato per calcolare l'hash della password e PHP usa == per confrontarle (per MD5, SHA-1 e plaintext).
Per MD5, SHA-1 e la famiglia SHA-2, usa il trucco noto da tempo (in realtà è una funzionalità documentata, vedi tabelle di confronto dei tipi PHP e numeri a virgola mobile) per cui in PHP , lo usa semplicemente per scopi . Qualsiasi password a qualsiasi altra password della lista. Questo è un trucco diverso dalle , basta notare la differenza tra .
'0e1' == '00e2' == '0'Questi sono tutti gli algoritmi con hash magici:
md5(md5(password))Per citare @0xb0bb, "ci sono altre applicazioni per gli hash magici oltre al confronto delle password (come i livelli di cache o i dati derivati dall'output di una funzione di hash) in cui questi algoritmi noti come insicuri, meno conosciuti e pseudo-hash possono essere trovati più facilmente."
Per plaintext, usa vari trucchi di conversione. La prima password corrisponderà solo alla seconda. I trucchi sono raggruppati per versioni PHP che li consentono.
bcrypt tronca le password a una lunghezza massima di 72 caratteri. Le password corrispondono se i primi 72 caratteri di entrambe le password coincidono.
descrypt (crypt DES UNIX tradizionale) tronca le password a una lunghezza massima di 8 caratteri. Le password corrispondono anche se i primi 8 caratteri di entrambe le password coincidono, vedi la sezione "General cross-check".
Se usi una password più lunga di 64 byte e la sottoponi a hash con PBKDF2-HMAC-SHA1, viene prima pre-hashata con SHA1, quindi PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2) perché sha1(password1) === bin2hex(password2). Un pre-hashing simile viene applicato in caso di PBKDF2-HMAC-SHA224 e PBKDF2-HMAC-SHA256.
Al momento c'è solo un hash magico in ciascuno grazie a Norbert Tihanyi, si spera che in futuro ne vengano aggiunti altri.
Usa === quando confronti qualsiasi cosa* in PHP, non ==. E usa password_hash() e password_verify() per l'hashing delle password in PHP, non usare MD5 o SHA-1. *Usa hash_equals() quando confronti gli hash.
Tutto è iniziato con questo tweet, ho generato QNKCDZO e 240610708 a febbraio 2014 e da allora si è diffuso in tutta la rete. Basta cercarlo su Google.
Nel 2014 ho usato il mio portatile, qualche ciclo for (o foreach?), molti cicli di CPU e una ventola esterna ma oggi puoi/dovresti usare una GPU e un hashcat modificato per farlo. Vedi questo articolo di Carl Löndahl e 0xb0bb.
Chick3nman e soci stanno anche lavorando alla loro versione di hashcat, restate sintonizzati.
Se ti serve una collisione reale alfanumerica, ecco una collisione MD5 alfanumerica di 72 byte con differenza di 1 byte, addirittura 1 bit, di Marc Stevens:
md5("TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
=
md5("TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
Nota che se ti registri con la prima password e accedi con la seconda, potrebbe comunque significare che il sito usa bcrypt(md5($password)), non solo md5($password). Questo avvolgimento dell'hash viene a volte usato quando si aggiorna l'hashing delle password ma dovrebbe essere usato solo temporaneamente.
Vedi il Progetto HashClash di Marc se sei interessato a queste collisioni reali o se vuoi crearne di tue.
Collisioni reali di hash LM di @solardiz (#35, grazie!):
db82323cb0693862: 2275490 o 0/*LUZ@44b3b60db75c15c1: 2716388 o 1}DC<XT585e239d32df1998: 8351762 o $;)5D|XVedi il tweet per sapere come generarne altri.