Comment puis-je créer un mot de passe qui, lorsqu'il est directement haché (sans aucun sel) avec md5, retournera une chaîne contenant les 8 caractères "SALT ME!". L'espoir est qu'un développeur naïf parcourant sa base de données d'utilisateurs verra le "hachage", réalisera l'insécurité de son application et finira par rendre le monde meilleur pour tout le monde.
Md5 produit 128 bits, soit 16 octets. Si j'avais un message de 16 octets, obtenir le mot de passe en clair d'origine équivaudrait à une pré-image, ce qui à ma connaissance est pratiquement impossible. Cependant, je ne recherche que 8 octets spécifiques dans mon hachage.
Est-il possible d'obtenir un tel mot de passe dans la journée sur un ordinateur typique? Si oui, comment puis-je calculer un tel mot de passe?
La sortie de MD5 est binaire: une séquence de 128 bits, généralement codée en 16 octets (techniquement, 16 octets, mais utilisons la convention commune des octets étant des octets).
Les humains ne lisent pas les bits ou les octets. Ils lisent caractères. Il existe de nombreuses pages de codes qui expliquent comment coder des caractères en octets et, de la même manière, décoder des octets en caractères. Pour presque tous (à cause de ASCII ), les octets de faible valeur (0 à 31) sont des "caractères de contrôle", donc pas vraiment représentables en tant que caractères . Donc, personne ne lit vraiment la sortie MD5 directement. Si quelqu'un "lit" les valeurs de hachage, ces valeurs sont très probablement encodées en caractères en utilisant l'une des rares conventions courantes pour cela. Les deux conventions les plus courantes sont hexadécimales et Base64 .
En hexadécimal, il n'y a que des chiffres et des lettres 'a' à 'f' (traditionnellement en minuscules pour les valeurs de hachage). Vous n'obtiendrez pas "SALTEZ-MOI!" dans une sortie hexadécimale ...
Avec Base64, l'encodage utilise les 26 lettres latines non accentuées (minuscules et majuscules), les chiffres et les signes '+' et '/'. Vous pourriez ainsi espérer "SaltMe" ou "SALTME". Maintenant ça est faisable, car chaque caractère en Base64 code 6 bits, donc une sortie à 6 lettres correspond à 36 bits seulement. La recherche d'un mot de passe qui donne "SaltMe" ou "SALTME" se fera en (en moyenne) 235 essaie, c'est-à-dire en quelques minutes ou heures avec du code décemment optimisé.
Notez, cependant, que quelqu'un qui passe du temps à lire les valeurs de hachage encodées en Base64 a probablement, disons, des "problèmes sociaux" et, en tant que tel, peut ne pas réagir comme vous l'espérez.
Et c'est fait: Lors du hachage avec MD5 puis le codage Base64 du résultat:
infjfieq
donne: SALTMEnBrODYbFY0c/tf+Q==
lakvqagi
donne: SaltMe+neeRdUB6h99kOFQ==
Il y a Rainbow table ensembles avec des hachages pré-calculés. Vous pouvez le rechercher pour une valeur de hachage qui contient les valeurs d'octets appropriées (EDIT: nécessiterait un forçage brut de pré-génération de hachages complets et de sondages, ce qui le rend beaucoup plus difficile à faire - voir commentaire de bonsaiviking to the réponse), s'il en existe une (par exemple, une contenant 0xBADBAD). S'il en existe un, à partir de la table Rainbow elle-même, vous pouvez récupérer le texte en clair à partir duquel ce hachage a été dérivé (et si vous utilisez ce mot de passe, il est, par définition, peu sûr car quiconque obtient la base de données peut l'inverser, et donc pas conseillé).
Il existe de nombreuses hypothèses dans cette approche.
Mais principalement l'hypothèse la plus importante est que quelqu'un consulte la base de données de milliers/milliers de milliers/dixmillions/utilisateurs/etc et détecte la valeur étrange d'un tas de hachages, et même alors d'une partie d'un hachage.
8 octets est 64 bits, ce qui est au-delà de la force brute. Je ne connais aucune attaque de pré-image sur md5, donc vous n'avez probablement pas de chance.
De plus, certains sites Web échappent ou restreignent votre jeu de caractères en tant que mesure (inefficace) contre SQLI