Give me my password...please
Introduction
Oublier son mot de passe est chose courante. La méthode pour redonner ce dernier à l'utilisateur n'est pas si triviale que ça.
On peut trouver 3 moyens pour obtenir sur un site son mot de passe oublié, on inscrit son email ou son login et l'une des 3 méthodes est alors utilisée, au choix :
- réinitialisation par le système du mot de passe automatiquement à une valeur (vu sur Fuzz, étrange : Your password has been reset to "password". Please login and change your password),
- l'envoi du passe en clair par mail,
- la ré-initialisation du mot de passe (pas d'envoi en clair de ce dernier) : envoi d'un lien vers une page Web pour en choisir un nouveau,
En général, on saisit son login ou son email, et le site vous envoie l'information adéquate. Bien entendu, pour les webmails (GMail), on trouve aussi la question secrète (par ex. : quelle était la couleur du cheval blanc d'Henri IV ?), qui se substitue au challenge de modification de récupération du mot de passe, et s'associe à l'envoi sur une email alternative du challenge (lien Web de modification du mot de passe). D'ailleurs, ne faites pas comme moi, assurez-vous que l'email alternative ne se trouve pas sur un ancien compte d'un fournisseur auquel vous n'avez plus accès (noos.fr à titre d'exemple).
En aparté, je souris souvent et reste étonné lorsque je m'aperçois d'une certaine naïveté ou de l'imprudence penseront d'autres, des utilisateurs qui n'hésitent pas à transférer leur mail avec leur login et mot de passe à des collaborateurs voire des personnes externes à leur entreprise. En sachant que leur mot de passe est souvent le même pour toutes les applications qu'ils utilisent, on imagine vite les conséquences de ce comportement (jugé irresponsable ?).
La 1ère solution ne me semble très honnêtement pas appropriée du point de vue de la sécurité, surtout que pour changer son mot de passe une fois connecté, cela se révèle plus du parcours du combattant que de la promenade printanière. La 2ème solution a vécu et semble être trop naïve pour le quidam peu au fait des bases de la sécurité.
Quelles options a-t-on pour mettre en œuvre la 3ème solution ?
Quelques critères :
- Le lien envoyé à l'utilisateur doit être temporaire, ceci afin de ne pas renouveler le transfert de mail, à sa belle-mère, à sa voisine, à sa secrétaire, ...
- Les paramètres du lien ne doivent pas être modifiables / modifiés par l'internaute: l'identifiant de l'utilisateur concerné, la date d'envoi, ...
Pour le 1er point, il suffit d'inscrire la date d'envoi du lien, soit en base, soit directement dans l'URL, et de refuser le lien si le délai dépasse 3 jours par exemple.
On se retrouve avec un lien à envoyer de ce type : http://mydummy.fr/reinit/?id=4&dte=2008-11-27
Pour répondre au point 2, deux solutions :
- ajouter une clé de HASH SHA-1 au lien : composée de la valeur des paramètres + une clé privée. On enverra http://mydummy.fr/reinit/?id=4&dte=2008-11-27&HASH=xyz. Il suffit alors de recomposer un HASH avec la valeur id + dte + secret puis de le comparer avec le HASH du lien. Il existe une méthode très utile qui permet de répondre à ce besoin : HashPasswordForStoringInConfigFile(chaineahasher,methodedehash), la méthode de hash est soit MD5, soit SHA1. On évitera la 1ère (MD5) car des collisions possibles ont été découvertes et n'est plus considérée comme sûre (si tu as un récent PC, alors amuse-toi à cracker un MD5). Cette méthode transformera l'entrée chaineahasher en Hash SHA1 puis transformera chaque lettre de la clé dans son équivalent en code Hexa (sans les %).
- crypter l'ensemble (voir ce billet à titre d'exemple) pour avoir un seul paramètre qs=valcrypte contenant l'ensemble de paramètres, mais rendus invisibles, cela évite la possibilité ou du moins de façon non triviale, de modifier la valeur des paramètres par un utilisateur. On veillera à URL encoder valcrypte (HttpUtility.UrlEncode(valcrypte) / HttpUtility.UrlDecode(valcrypte)). Cela donnera ce type de lien : http://mydummy.fr/reinit/?qs=VEQ5emM1SWk4ZUVZNmNDbytDVDYwbEhGMWMrWH
On prendra une attention toute particulière à ce que le lien de ré-initialisation passe sur la majorité des Webmails (GMail, Free, Hotmail, ...) ou autres clients de messagerie (Outlook, Thunderbird et même...Lotus Notes). L'URLEncoder est une bonne base pour se protéger des caractères mal interprétés par les clients de messagerie afin qu'ils reconstruisent l'URL pour qu'elle soit cliquable.
Conclusion
Quelques techniques parmi d'autres, je dois en oublier, mais en général, le challenge pour une ré-initialisation me parait la meilleure solution, la plus sécurisée en tout cas.
Commentaires
Bon article, merci
À noter que le SHA1 en tant que tel est lui aussi facilement crackable aujourd'hui, à l'aide de rainbow tables.
La solution est, comme tu l'as fait, de saler les données en mélangeant plusieurs clefs que l'attaquant ne pourra pas deviner et qui génèrent un code brut, avant d'être hashé, d'au moins 15 caractères (il faudrait plusieurs centaines de go de rainbow tables rien que pour retrouver la valeur première à partir du hash, et l'attaquant devra ensuite deviner comment elle a été salée).
Peut-être serait-il bon d'insister sur ce point