Oct 292013
 

Un article qui décrit l’ algorithme md5crypt qui est toujours

  • utilisé par les IOS CISO (secret 5)
    Exemple: $1$28772684$iEwNOgGugqO9.bIz5sk8k/

  • proposé par htpassword. Option -m
    Exemple: $apr1$VaN8AS0b$Z7hfqYrZ/.yOuxQepKEHe1

  • utilisé dans /etc/shadow (les distributions récentes n’ utilisent plus md5crypt mais sha512crypt).
    Exemple: $1$28772684$iEwNOgGugqO9.bIz5sk8k/

Algorithme

Le mot de passe et le « salt » sont fournis. Le « salt » est tronqué à 8 caractères

Calcul de Hash_A

On calcule un hash md5 selon l’algo suivant. je le nomme Hash_A. Le résultat est au format digest(raw).
|| signifie concaténation

hash_A = md5(password || salt || password)

Calcul de Hash_B

On calcule un deuxième hash md5 selon l’algo suivant. je le nomme Hash_B
Hash_A est utilisé pour calculer Hash_B.

Hash_B = md5(
password
||
$1$
||
salt
||
Hash_A (pour chaque bloc de 16 octets composant le password.
Si le password est inférieur à 16 octets, on passe a l’ étape suivante.
||
N octets de Hash_A pour les N octets restant du password.
||
représentation binaire de la longueur du password, en commençant par le bit de poids faible

si le bit est égale à 1 , on ajoute le premier caractère du password
si le bit est égale à 0 , on ajoute la valeur \x00 (null)
)

Calcul de Hash_C

Hash_B est utilisé pour calculer Hash_C.

Initialisation: Context_C est vide

Pour 1000 itérations (indice de 0 à 999 inclus)

si indice est impair alors Context_C = Context_C || password

si indice est pair

à l’itération 0 alors Context_C = Context_C || Hash_B
aux itération paires suivantes, Context_C = Context_C || (Hash_C précédent)

si l’indice n’est pas un multiple de 3 , Context_C = Context_C || salt
(pour savoir si c’est un multiple de 3, il suffit d’ utiliser la fonction modulo 3)

si l’indice n’est pas un multiple de 7 , Context_C = Context_C || password
(pour savoir si c’est un multiple de 7, il suffit d’utiliser la fonction modulo 7)

si l’indice est pair , Context_C = Context_C || password

si l’indice est impair

à l’itération 1 alors Context_C = Context_C || Hash_B
aux itérations impaires suivantes, Context_C = Context_C || (Hash_C précédent)

si indice est pair, Context_C = Context_C || password

Hash_C = md5 (Context_C)
Transposition et encodage base64 du Hash_C

Hash_C :        0, 1,  2, 3, 4,  5, 6, 7,  8, 9, 10 , 11, 12, 13, 14, 15  
Transposition : 0, 6, 12, 1, 7, 13, 2, 8, 14, 3,  9,  15,  4, 10,  5, 11

Découpage en groupe de 3 octets:

  • le premier groupe de 3 octets : position 0,6,12 du Hash_C
  • le deuxième groupe de 3 octets : position 1,7,13 du hash_C
  • le troisième groupe de 3 octets : position 2,8,14 du Hash_C
  • le quatrième groupe de 3 octets : position 3,9,15 du Hash_C
  • le cinquième groupe de 3 octets : position 4,10,5 du hash_C

Encodage base 64 des 16 octets en 22 caractéres (ajout de 4 bits de bourrage égales à 0)

Modèle d’encodage base64 :

          1         2         3         4         5         6
0123456789012345678901234567890123456789012345678901234567890123
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Pour le premier groupe de 3 octets


octet 0 0octet 6 0octet 12
aaaabbBB ccccCCCC DDddeeee

Découpage en 4 blocs de 6 bits


1er bloc : ddeeee
2ième bloc : CCCCDD
3ième bloc : BBBcccc
4ieme bloc : aaaabb

Même principe pour les 4 groupes de 3 octets suivants.

Pour le dernier octet

octet 11
AAaabbbb

Découpage en 2 blocs de 6 bits (bourrage à gauche avec 4 bits à 0)

(0000)AA aabbbb


1er bloc : aabbbb
2ieme bloc : 0000AA

Programme python

Pour finir un programme en python qui calcule un hash md5crypt
Vous devez fournir le salt et le password. Lignes [94,95] et [103,104].

Pour sélectionner tout le code , double-cliquez dans la fenêtre .

# -*- coding: cp1252 -*-
 
import hashlib
 
MAGIC = '$1$'   # Magic string
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 
def to64 (v, n):
   ret = ''
   while (n - 1 >= 0):
      n = n - 1
      ret = ret + ITOA64[v & 0x3f]
      v = v >> 6
   return ret
 
def apache_md5_crypt (pw, salt):
   return unix_md5_crypt(pw, salt, '$apr1$')
 
def unix_md5_crypt(pw, salt, magic=None):
 
   if magic==None:
      magic = MAGIC
 
   if salt[:len(magic)] == magic:
      salt = salt[len(magic):]
 
   # le "salt"  au maximum 8 caractères
   import string
   salt = string.split(salt, '$', 1)[0]
   salt = salt[:8]
 
   ctx = pw + magic + salt
 
   # hash_A
   final = hashlib.md5(pw + salt + pw).digest()
 
   for pl in range(len(pw),0,-16):
      if pl > 16:
         ctx = ctx + final[:16]
      else:
         ctx = ctx + final[:pl]
 
   # ctx = password + magic + salt + raw_hash_final (nombre de caractère du password)
 
   i = len(pw)
   while i:
      if i & 1:
         ctx = ctx + chr(0)
      else:
         ctx = ctx + pw[0]
      i = i >> 1
 
   # si le premier de la longueur (i) est à 1 , on ajoute \x00
   # si le premier de la longueur (i) est à 0 , on ajoute la première lettre du mot de passe
 
   # print hash_B
   final = hashlib.md5(ctx).digest()
 
   # itération pour lutter contre le bruteforce.
 
   for i in range(1000):
      ctx1 = ''
      if i & 1:
         ctx1 = ctx1 + pw
      else:
         ctx1 = ctx1 + final[:16]
 
      if i % 3:
         ctx1 = ctx1 + salt
 
      if i % 7:
         ctx1 = ctx1 + pw
 
      if i & 1:
         ctx1 = ctx1 + final[:16]
      else:
         ctx1 = ctx1 + pw
      final = hashlib.md5(ctx1).digest()
 
   passwd = ''
   passwd = passwd + to64((int(ord(final[0])) << 16) |(int(ord(final[6])) << 8) |(int(ord(final[12]))),4)
   passwd = passwd + to64((int(ord(final[1])) << 16) |(int(ord(final[7])) << 8) |(int(ord(final[13]))),4)
   passwd = passwd + to64((int(ord(final[2])) << 16) |(int(ord(final[8])) << 8) |(int(ord(final[14]))),4)
   passwd = passwd + to64((int(ord(final[3])) << 16) |(int(ord(final[9])) << 8) |(int(ord(final[15]))),4)
   passwd = passwd + to64((int(ord(final[4])) << 16) |(int(ord(final[10])) << 8)|(int(ord(final[5]))),4)
   passwd = passwd + to64((int(ord(final[11]))), 2)
 
   return magic + salt + '$' + passwd
 
if __name__ == "__main__":
 
   # mot de passe :  hashcat  -  hash : $1$28772684$iEwNOgGugqO9.bIz5sk8k/
   # unix et cisco
   # arguments
   password="hashcat"
   salt="28772684"
   print "unix ou cisco"
   # arg01: password
   # arg02: salt
   print unix_md5_crypt(password, salt)
 
   # apache
   # mot de passe :  hashcat  -  hash : $apr1$71850310$gh9m4xcAn3MGxogwX/ztb.
   # arguements
   password="hashcat"    
   salt="71850310"
   print "apache"
   # arg01: password
   # arg02: salt
   print apache_md5_crypt(password,salt)
 Publié par à 0 h 44 min

 Laisser un commentaire

Vous pouvez utiliser ces balises et attributs HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(requis)

(requis)