Générateurs de mots de passe : vraiment aléatoires ?

générateurs mots de passe aléatoires

Combinée à d’autres faiblesses, une faille dans le générateur de nombres aléatoires de Kaspersky Password Manager affaiblissait la sécurité des mots de passe.

Pourquoi faire compliqué quand on peut faire simple ? Il est tentant de dresser ce constat à la lecture du dernier billet sur le blog de Donjon. L’équipe sécurité de Ledger revient sur son analyse de Kaspersky Password Manager… et sur les multiples fragilités qu’elle y a dénichées au niveau de la création de mots de passe. Aussi bien dans l’algorithme lui-même que dans le générateur de nombres pseudo-aléatoires qui le sous-tend.

Pour mettre les choses en perspective, les chercheurs évoquent un produit concurrent : KeePass. Celui-ci inclut trois méthodes pour générer des mots de passe. La plus simple utilise un jeu de caractères et va les « piocher » un par un. Le tirage dépend d’un nombre aléatoire. La fonction qui le génère est uniforme, au sens où toutes les valeurs possibles ont autant de chances de sortir. Elle a notamment fait, pour cela, l’objet d’une adaptation anti-biais modulo.

Avec KPM, les mots de passe sont créés dans le respect d’une « stratégie ». Ses paramètres sont les suivants :

  • Longueur du mot de passe (par défaut, 12 caractères)
  • Présence ou non de majuscules, de minuscules et de chiffres
  • Utilisation de caractères spéciaux (ensemble personnalisable)

KPM, tel qu’étudié, utilise lui aussi une méthode de « pioche » dans un jeu de caractères aléatoire. Mais elle se fonde sur des mécanismes plus complexes. À la racine, il y a deux nombres en virgule flottante (r1 et r2), générés aléatoirement et compris dans l’ensemble [0,1[. On calcule leur produit, qu’on multiplie par la longueur du jeu de caractères. Il en résulte, arrondi à l’entier, la position du caractère à récupérer.
On aura constaté que la distribution de (r1 x r2) n’est pas uniforme : il est plus probable d’obtenir des valeurs basses (proches de zéro). Un choix volontaire, estiment les chercheurs.

Un algorithme complexe, mais vulnérable

L’ordonnancement du jeu de caractères dépend de la fréquence inverse d’apparition des lettres – dans une langue qu’on peut supposer être l’anglais. Mais cet ordonnancement n’est pas fixe : il est redéfini à chaque fois que l’algorithme pioche un caractère, ce dernier étant intégré au calcul.
Une telle approche semble destinée à piéger les outils génériques de craquage de mots de passe. Lesquels testent en priorité des combinaisons qu’un humain aurait tendance à générer – en utilisant donc des lettres « habituelles », à forte fréquence d’apparition. Le souci, c’est que cette robustesse peut devenir une faiblesse contre des outils de craquage développés spécifiquement pour un tel mécanisme.

Le principal problème est ailleurs, néanmoins. En l’occurrence, dans la façon dont sont calculés r1 et r2. Au moment où Ledger Donjon avait commencé à s’intéresser à KPM, la version web utilisait la fonction Math.random(). Avec, comme générateur sous-jacent sur Chrome, Firefox et Safari, xorshift128+. Mozilla, entre autres, a reconnu sa fragilité.

La version desktop utilisait quant à elle un générateur de type Mersenne Twister : mt19937, tiré de la bibliothèque Boost. Premier inconvénient, selon les chercheurs : connaître une partie des résultats produits peut suffire à prédire les suivants. L’outil randcrack exploite cette faiblesse contre le module random de Python, qui repose sur une implémentation similaire de mt19937.

Dans l’absolu, ce levier reste difficile à actionner sur KPM. Ne serait-ce que parce qu’il faut connaître au moins 624 caractères produits au préalable. Soit, à la longueur par défaut, 52 mots de passe. Il y a toutefois d’autres portes ouvertes. Par exemple, le fait qu’une instance du générateur soit créée à chaque fois qu’un mot de passe est généré. KPM ne peut donc produire qu’un nombre fini de mots de passe (232) pour un charset donné.

Un générateur à très faible entropie

Surtout, il y a une faille dès l’initialisation du générateur qui calcule r1 et r2. La graine n’a rien d’aléatoire, en ce qu’elle se fonde sur un unique élément d’entropie : l’horloge système (valeur en secondes). Autrement dit, à une seconde donnée, toute instance desktop de KPM générera exactement le même mot de passe.
Dans ce contexte, le nombre de possibilités pour un charset donné est limité. Et on peut nettement réduire le travail de recherche d’un mot de passe si on connaît – même approximativement – sa date de création.

Pourquoi cette vulnérabilité est-elle passée inaperçue ? D’après Ledger Donjon. C’est lié à l’animation qui se déclenche lors de la création d’un mot de passe. Elle dure plus d’une seconde. Temps pendant lequel elle affiche des chaînes de caractères aléatoires, quand bien même le mot de passe est déjà calculé.

Initialement averti à la mi-2019, Kaspersky a récemment annoncé avoir colmaté la faille (CVE-2020-27020). Le correctif est intégré à partir de :

  • KPM 9.0.2 Patch F sur Windows
  • La version 9.2.14.872 sur Android
  • La version 9.2.14.31 sur iOS

Sur la version web, Math.random() a laissé place à window.crypto.getRandomValues().

Photo d’illustration © Alperen Yazgı – Unsplash