• # Mots de passe et imprécisions...

    Posté par . En réponse à la dépêche Linux Mint a été compromise. Évalué à 10. Dernière modification le 07 mars 2016 à 13:55.

    Pas mal d'imprécisions dans le paragraphe sur le stockage des mots de passe: confusion entre les hash tables et rainbow tables, méprise sur l'utilité du salt, et pas de mention de l'utilisation des GPU qui sont quand même la méthode à l'état de l'art pour le cassage des mots de passe.

    Le problème général avec le stockage des mots de passe est que même si la fonction de hachage h utilisée pour hasher un mot de passe p est robuste, ie il est impossible de déterminer p à partir de h(p), il est (relativement) facile d'énumérer tout les p. En effet l'espace P des mots de passe p est relativement petit: on ne peut pas demander aux utilisateurs de retenir des mots de passe avec 25 caractères aléatoires. En général, on demande 8-15 caractères, ce qui génère un espace petit. Par exemple pour un mot de passe totalement aléatoire de 8 caractères comprenant majuscules, minuscules et chiffres, il y a ~247 possibilités, ce qui est énumérable avec les moyens actuels (une workstation avec un GPU à 1000€ vous permet de casser ça en quelques jours).

    Un des premiers moyen utilisés pour accélérer le cassage des mots de passe a été d'utiliser des tables de hash précalculés. L'idée est simple: pour une fonction de hachage h donnée (exemple: h=md5 ou h=sha256), on précalcule h(p) pour tout les mots de passe p de 0-8 caractères. Ensuite, pour un hash h(p) donné, on cherche h(p) dans la table, et on retrouve p. Le problème est que ces tables précalculées ont une taille rédhibitoire: on est déjà à plusieurs téraoctets pour des mots de passe de 5-6 caractères, et la taille augmente exponentiellement avec le nombre de caractères (donc on est à des centaines de teras pour 8 caractères). Les rainbow tables ont été inventées pour résoudre ce problème. Très grossièrement, les rainbow tables permettent d'obtenir les mêmes résultats que les tables de hash précalculés, pour une fraction de l'espace de stockage (dizaines à centaines de gigas). J'ai l'impression que l'auteur confond les rainbow tables, avec les hash tables , une structure de données couramment utilisée qui n'a rien de spécifique à la cryptanalyse. On peut aujourd'hui facilement télécharger des rainbow tables sur internet pour de nombreuses fonctions de hachage (je vous laisse chercher hein...).

    Pour se protéger des attaques basées sur les rainbow tables, on utilise un salt ou sel. L'idée est très simple: au lieu de stocker le hash du mot de passe h(p) dans la base de données, on stocke le hash de concaténation du mot de passe p et du sel s : h(s.p). La rainbow table qui stocke les correspondances h(p) -> p n'est donc plus utilisable, il faut recalculer une rainbow table pour chaque sel s. Plusieurs informations érronées dans l'article: les sels ne pas des information secrètes, vous pouvez les stocker dans la base de données, avec les hash. Même si le sel n'est pas secret, et leake avec les hashs, vous êtes protégés contre les attaques basées sur les rainbow tables. La seule contrainte est que le sel doit être de taille suffisante (64-128 bits c'est très bien), et différent pour chaque utilisateur. Il ne faut pas utiliser un sel unique pour toute la base de données, parce qu'à ce moment il devient possible de calculer une rainbow table pour votre base de données. Si le sel est différent pour chaque utilisateur, il faut calculer une rainbow table par utilisateur (ce qui la rend inutile, évidemment). Je le répète: un sel différent pour chaque utilisateur, et stockez-le dans la base de données et vous êtes protégés des rainbow tables.

    Bon, malheureusement, les rainbow tables ne sont plus la méthode à l'état de l'art pour le cassage des mots de passe. C'était le cas il y a dix ans, mais depuis on utilise des GPUs. Les GPUs sont très efficaces pour calculer des fonctions de hashage: une machine avec 8 GPU (~8000€) peut calculer plus de 14 milliards de hash SHA256 par seconde (voir Performance hashcat). En d'autres termes, ce genre de machine peut bruteforcer 4 milliards de mot de passes par seconde. En quelques semaines/mois, vous pouvez casser n'importe quel mot de passe de 10 caractères (Speed Hashing). Pour 9 caractères, c'est quelques heures/jours. Et ce même si un sel a été utilisé.

    Pour répondre à ce problème, une des techniques utilisés est le key stretching (mais malheureusement seuls peu de systèmes/sites utilisent cette technique). L'idée est simple: au lieu de hasher une seule fois h(s.p), on hashe itérativement un nombre configurable de fois (de l'ordre de quelques dizaines de milliers à quelques centaines de milliers) h(h(h(...h(s.p))). Parmi les algorithmes qui utilisent le key stretching on trouve PBKDF2 et sha512crypt. Par exemple, cryptsetup (utilisé pour le chiffrement disque sous Linux) hashe les mots de passe en utilisant sha256 pendant 2 secondes (sur ma machine, ça fait ~50000 itérations de sha256), GPG hashe les mots de passe en faisant 65536 itérations de SHA1. PAM (sha512crypt) fait 5000 itérations de sha512 (d'ailleurs de nos jours, 5000 itérations de sha512, c'est un peu léger). L'uilisation de PBKDF2 ou sha512crypt est aujourd'hui chaudement recommandée pour atténuer les attaques utilisant des GPUs.

    Le problème du key stretching est que les GPUs restent toujours très efficaces pour casser les mot de passe. Même si vous réduisez le nombre d'essais de 4 milliards/s à 100 000/s, ça reste toujours beaucoup, surtout si vos utilisateurs ont des mots de passe "normaux": par exemple 8 caractères alphabétiques lower-case. Il est aussi possible de construire du hardware spécialisé (FPGA, ASIC) pour accélérer encore plus le cassage des mot de passage. Ça se voit avec les ASIC pour miner du bitcoin (qui calcule plein de fois des hash sha256) qui sont capables de calculer des centaines de milliards de sha256 par seconde.

    Pour répondre à ce problème, on est en train d'inventer des fonctions de hashage memory-hard: le hash d'un mot de passe doit non seulement être couteux en temps mais aussi utiliser une certaine quantité de mémoire (par exemple 64Mo-1Go. Pour info, pour sha512 ou sha256, on est <1Ko). Ça permet de réduire à néant l'efficacité des GPU et du hardware spécialisé. Pour un GPU avec 16Go, il n'y a que "250 blocks" de 64Mo, ce qui l'empêche de calculer plus de 250 hash par seconde. Même chose pour les ASIC: des grandes quantité de mémoire restent couteuses en espace silicium, et aussi en complexité d'adressage. Ces fonctions de hashage memory-hard restent à l'état de recherche/prototype. En Juin 2015 a eu lieu la Password Hashing Competition dont le but était de sélectionner pour standardisation une fonction de hashage de mot de passe memory-hard. Le gagnant a été argon2 dont le code source est distribué sous CC0.

    En résumé :

    • Si vous êtes administateur ou développeur: utilisez un sel différent pour chaque utilisateur et stocké en base de données. Utilisez sha512crypt ou PBKDF2 1 avec le nombre maximal d'itérations que vous pouvez supporter. Si un délai de 0.5-1s pour une vérification de mot de passe est acceptable, utilisez 100000 itérations. Suivez l'évolution de argon2 (par exemple l'auteur de cryptsetup a annoncé sa volonté de l'utiliser), et implémentez-le lorsqu'il sort de sa phase de beta. Je fais partie de ceux qui pensent que ce n'est pas aux utilisateurs de retenir des mots de passe de 20 caractères aléatoires: c'est au admins de rendre les attaques par bruteforce impraticables.

    • Si vous êtes utilisateur, et que vous voulez protéger votre mot de passe quoi qu'il arrive (ie même si l'administateur d'un site n'utilise pas de sel ni de key stretching), alors il faut un mot de passe d'au moins 13 caractères aléatoires. Sinon, éviter de partager les mots de passe entre différents service, éventuellement en utilisant un wallet ou keepass (les conseils données dans l'article sont tout à fait valides sur ce domaine).

    [1]: Je connais mal bcrypt et scrypt mais ce sont probablement des alternatives correctes. Gardez à l'esprit qu'elles ne sont cependant pas standardisées.