Message Digest 5

To the non-french speaker, note that you can translate the articles using the Google Trad widget situated at the bottom of all pages.


MD5 (Message digest 5) est une fonction de hachage créée par Ronald Rivest en 1991. Cette fonction permet de hacher des données afin de n’en garder qu’une empreinte.

Pour comprendre ce qu’est un hash, faisons une analogie simple. Votre main est particulière, elle a une forme, des doigts plus ou moins longs ainsi que des tracés différents de celle de votre voisin. En se servant de l’empreinte de votre main on peut vous identifier vous en tant qu’individu sans connaître le tracé exact des lignes de vos mains. Et bien pour un message hashé c’est pareil. A partir de son empreinte on peut reconnaître le message initial sans pour autant connaître parfaitement son contenu.

Pourquoi hasher des données? La raison est simple, cela permet de les protéger. En effet les fonctions de hashage (à la différence des fonctions de cryptage) produisent des résultats qui ne sont pas décryptables.

Prenons le cas ou les mots de passe d’un site ne sont pas hashés. Si un pirate dérobe la base de données alors il pourra tenter de se connecter à l’application piratée mais aussi à d’autres applications en utilisant l’identifiant et le mot de passe dérobé.

En revanche si les mots de passe sont hashés alors le pirate sera bloqué puisqu’il aura l’empreinte du mot de passe mais pas le mot de passe en lui même. C’est une protection de base dans les applications web, on stocke l’empreinte hashée et non pas le mot de passe. Ainsi lors de l’authentification on comparera l’empreinte du mot de passe stockée dans la base de données à l’empreinte de la donnée envoyée via le formulaire d’authentification.

Dans cet article nous verrons dans un premier temps comment fonctionne la fonction MD5 puis nous verrons comment la « cracker », enfin nous verrons comment sécuriser nos données au maximum.

I/Algorithme MD5

Pour utiliser MD5 il faut absolument que le message à hashé soit un multiple de 512 (bits).
Si votre message a un poids de 350 bits alors on va le compléter jusqu’à ce qu’il fasse 448 bits. Pour cela on va concaténer au message un “1” qui démarque la fin du message utile puis des “0”. C’est une méthode dites de padding que l’on retrouve dans l’envoi de datagrammes sur Internet. Puis on va ajouter 64 bits qui représentent la taille du message.

completion

Notre message fait donc 512 bits.
Le résultat de l’algorithme MD5 est de longueur 128 bits. Donc l’algorithme travaille avec des paquets de données de 128 bits. Ces 128 bits sont divisés en 4 mots de 32 bits chacun.

Conventionnellement on les appelle A,B,C et D et on les initialise avec ces valeurs (qui sont des constantes hexadécimales) :

A: 01 23 45 67
B: 89 ab cd ef
C: fe dc ba 98
D: 76 54 32 10

Puis on va définir quatre fonctions non linéaires booléennes. Ces quatre fonctions prennent en argument des mots de 32 bits et renvoient un résultat de 32 bits :

F(X,Y,Z) = (X et Y) ou (non(X) et Z)
G(X,Y,Z) = (X et Z) ou (Y et non(Z))
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X or not(Z))

A partir de là on va rentrer dans la boucle de l’algorithme.

Quelques notations :

T[] est un tableau allant de 1 à 64, initialisé via la fonction sinus.
M[] est le message à hacher.
<<< n est un décalage de n bits sur la gauche

 /* Pour chaque blocs de 16 mots */
   For i = 0 to N/16-1 do

     /* Copier le bloc i dans X. */
     For j = 0 to 15 do
       Set X[j] to M[i*16+j].
      /* Fin de la boucle sur J */

     /* On stocke les valeurs de A, B, C et D. */
     AA = A
     BB = B
     CC = C
     DD = D

     /* Premier tour 1. */
     /* On note[abcd k s i] l'opération suivante
          a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
     /* Faire les 16 opérations suivantes. */
[ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
[ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8]
[ABCD  8  7  9]  [DABC  9 12 10]  [CDAB 10 17 11]  [BCDA 11 22 12]
[ABCD 12  7 13]  [DABC 13 12 14]  [CDAB 14 17 15]  [BCDA 15 22 16]


       Pour la première opération voici le calcul effectué 
               a=b+((a+F(b,c,d) + X[0] + T[1] <<
     /* Second tour. */
     /* On note [abcd k s i] l'opération suivante
          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
     /* Faire les 16 opérations suivantes. */
[ABCD  1  5 17]  [DABC  6  9 18]  [CDAB 11 14 19]  [BCDA  0 20 20]
[ABCD  5  5 21]  [DABC 10  9 22]  [CDAB 15 14 23]  [BCDA  4 20 24]
[ABCD  9  5 25]  [DABC 14  9 26]  [CDAB  3 14 27]  [BCDA  8 20 28]
[ABCD 13  5 29]  [DABC  2  9 30]  [CDAB  7 14 31]  [BCDA 12 20 32]

     /* Troisieme tour. */
     /* On note [abcd k s t] l'opération suivante
          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
     /* Faire les 16 opérations suivantes. */
[ABCD  5  4 33]  [DABC  8 11 34]  [CDAB 11 16 35]  [BCDA 14 23 36]
[ABCD  1  4 37]  [DABC  4 11 38]  [CDAB  7 16 39]  [BCDA 10 23 40]
[ABCD 13  4 41]  [DABC  0 11 42]  [CDAB  3 16 43]  [BCDA  6 23 44]
[ABCD  9  4 45]  [DABC 12 11 46]  [CDAB 15 16 47]  [BCDA  2 23 48]

     /* Quatrieme tour. */
     /* On note [abcd k s t] l'opération suivante
          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
     /* Faire les 16 opérations suivantes. */
[ABCD  0  6 49]  [DABC  7 10 50]  [CDAB 14 15 51]  [BCDA  5 21 52]
[ABCD 12  6 53]  [DABC  3 10 54]  [CDAB 10 15 55]  [BCDA  1 21 56]
[ABCD  8  6 57]  [DABC 15 10 58]  [CDAB  6 15 59]  [BCDA 13 21 60]
[ABCD  4  6 61]  [DABC 11 10 62]  [CDAB  2 15 63]  [BCDA  9 21 64]

 A chaque tour on stocke les nouvelles valeurs de nos quatre 
 variables
     A = A + AA
     B = B + BB
     C = C + CC
     D = D + DD

   /*Fin de la boucle sur i*/

Documentation officielle RFC 1321

A la fin de l’algorithme, nous récupérons nos quatre variables A, B, C et D, on les concatène et nous obtenons notre hash.

A priori l’algorithme semblait incrackable… Jusqu’à ce qu’on se rende compte qu’avec deux messages différents on pouvait trouver la même empreinte. Et là, ça devient dangereux.

II/Casser MD5

Deux problèmes majeurs ont rendu MD5 obsolète. Le premier c’est que l’algorithme est très rapide à exécuter. Hors s’il est rapide alors cela veut dire qu’il est vulnérable au bruteforce. J’ai lu qu’avec une carte graphique de 2016 on pouvait effectuer 350 millions de comparaison par secondes donc bon…

Pour bruteforce un hash, il va falloir le comparer à un ensemble d’autres hash contenus dans un dictionnaire. Si la valeur du hash est identique à celle d’un des mots du dictionnaire alors on a trouvé le message.

Pour cela nous disposons de très bons outils comme John The Ripper. Une version maintenue par la communauté est disponible sur Kali, elle s’appelle Jumbo et permet de cracker de nombreux formats de mots de passe en plus de donner d’autres fonctionnalités.

Ensuite il vous faudra un bon dictionnaire de mots. Il y en a un de 3000 mots inclus dans l’outil mais ce n’est pas assez… Nous on préfère travailler avec une base de données de… 1,5 milliards de mots non ?

Cette liste, c’est Stun qui l’a faite et elle est disponible gratuitement ici

(Attention, le fichier compressé fait 4,2Gb, en décompressé il en fait 15.)

Bon, on est prêt pour notre attaque. Maintenant on va choisir un mot de passe (simple parce que j’ai pas envie d’attendre trois heures) : « bonjour ». Si on le hash on obtient ceci :

f02368945726d5fc2a14eb576f7276c0

On va créer un fichier texte sur le bureau que l’on va nommer hash.txt (vous pouvez l’appeler comme bon vous semble). Et dans ce fichier nous allons placer notre hash. Retournons sur notre invite de commande et entrons cette commande :

john –format=raw-md5 –show hash.txt

On spécifie le format du hash (md5) puis on spécifie que l’on veut que john nous retourne le résultat (–show). Enfin on donne à John le fichier qui contient le hash. Et voici le résultat :

hash

Ici je ne me suis pas servi de notre dictionnaire de 15Go puisque je savais que le mot ne serait pas long à retrouver. Si j’avais voulu m’en servir j’aurais rajouter l’option –wordlist= »chemin du dico ».

De nombreuses options sont disponibles mais je vous laisse lire la documentation. 😛

III/Protéger ses données

MD5 est obsolète. Donc si vous voulez vraiment protéger vos données, vous devez passer à un autre algorithme de hachage (CF les articles à venir).

On peut aussi utiliser un salt (un gré de sel) qui servira à créer une empreinte unique. Dans ce cas ci, si le salt n’est pas connu du pirate (i.e si sa valeur n’est pas stockée dans un fichier JavaScript ou si sa valeur est modifiée régulièrement) alors le pirate sera bloqué.

Par exemple, en PHP vous pouvez utiliser ce bout de code :

<!–?php
//Script d’inscription
// Variable préfixe
$pre=new DateTime( »,new DateTimeZone(‘Europe/Paris’));
//Variable suffixe
$suf=$_POST[‘nomUtilisateur’];
//Notre hash
$hash =md5($pre.$mdp.$suf);
//Stockage du hash dans une base de données
?>

Suivant la date d’inscription de l’utilisateur et son nom alors le hash sera totalement différent. Dans ces conditions le crakage du hash sera extrêmement complexe (bien évidement ici il faudra stocker la date et l’horaire d’inscription de l’utilisateur).

Un commentaire

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l'aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s