Twitter Facebook Google Plus Linkedin email

Cracker un hash custom avec john the ripper

Au cours de mon dernier test d'intrusion je suis tombé sur un CMS affecté par plusieurs injections SQL. Après une exploitation très rapide grâce à sqlmap, j'ai pu récupérer les hashs des mots de passe.

Cependant, ce n'était pas un type de hash standard. Il s'agissait d'une fonction de hashing home-made utilisant le nom de l'utilisateur comme salt en plus d'une constante :

<?php
public static function getPasswordHash($username, $plainTextPassword) {
    return md5($username . ":pimcore:" . $plainTextPassword);
}

Ce type de hash peu courant n'est pas défini les logiciels de bruteforce de base (john the ripper, hashcat, ...). Cependant, john the ripper supporte la création de fonctions de hashing dynamique, et cela, sans avoir à recompiler le soft, très pratique !

Après avoir rtfm la doc sur les hashs dynamiques et les scripts dynamiques, j'ai pu me créer ma petite fonction de hashing et l'ajouter dans mon fichier john.conf :

####################################################################
# Pimcore return md5($username . ":pimcore:" . $plainTextPassword);
####################################################################
[List.Generic:dynamic_2001]
# Description, pour faire beau dans l'UI
Expression=md5($u . ":pimcore:" . $p) (pimcore)

# On va utiliser le nom d'utilisateur dans le buffer
Flag=MGF_USERNAME

# On définit la constante que l'on va ajouter plus tard au buffer
Const1=:pimcore:

# Nettoie le buffer
Func=DynamicFunc__clean_input
# Ajout du nom de l'utilisateur au buffer
Func=DynamicFunc__append_userid
# Ajout du nom de la constante au buffer
Func=DynamicFunc__append_input1_from_CONST1
# Ajout du password candidat au buffer
Func=DynamicFunc__append_keys
# Calcul le hash du buffer en utilisant md5
Func=DynamicFunc__crypt_md5

# Fonction de vérification obligatoire
Test=$dynamic_2001$f67580872732ecebbff061108e408308$$Ujacky:test

Après, un coup de john --format=dynamic_2001 hashdump.txt et le tour est joué.

Au passage, bien qu'il s'agisse d'un hash salé (ici avec le nom d'utilisateur) qui rend inefficaces les tables rainbows, ce type de protection est inefficace et presque inutile. Il faut utiliser les fonctions password_hash() et password_verify() de PHP qui utilisent bcrypt, un hash salé avec plusieurs itérations (hash(hash(hash...) afin de rendre le bruteforce plus difficile.