Sécuriser les mots de passe avec les hashs et les salts
- Par Emacs
- 19 commentaires
- 4 172 lectures
- Format PDF
- RSS - Atom
Comme nous le savons tous, le but d'un mot de passe est avant tout de rester connu d'une personne ou d'un groupe de personne. Sa divulgation entraine alors la perte complète de son efficacité et de sa sécurité. Lorsque le mot de passe devient connu d'une personne tierce, alors cette dernière peut par exemple s'approprier des droits sur une application et compromettre son fonctionnement normal. Un mot de passe est une donnée extrêmement sensible et convoitée par des pirates, quelle que soit l'application qui l'utilise.
Qu'est-ce qu'un mot de passe ?
Métaphoriquement, un mot de passe peut être perçu comme une clé ouvrant une / des porte(s) à celui qui le détient. Ainsi, cet utilisateur s'approprie des droits supplémentaires que d'autres personnes n'ont pas. Il ne tient alors qu'à lui de ne pas le divulguer pour que les privilèges qui lui sont conférés ne soient pas détournés par une tierce personne mal intentionnée.
Lorsqu'un / des mots de passe doivent être sauvegardés dans un système d'information (base de données, fichiers de configuration...), cela devient plus compliqué. En effet, la sécurité ne tient plus qu'à une personne mais repose à présent sur la sécurité du système d'information lui même (accès physique, identifiants pour se connecter dessus) ainsi que sur la manière dont sont stockés ces mots de passe dans le SI.
Sécurité des mots de passe dans un système d'information
Il est évident qu'une protection accrue des mots de passe dans le système d'information doit être mise en place. Le stockage des mots de passe en clair dans le système d'information devient alors impossible. Pourquoi ? Prenons le cas typique d'une base de données dans laquelle sont stockés les identifiants des utilisateurs d'un extranet d'une entreprise. Cela sous-entend qu'il y'ait une politique de sécurité à plusieurs niveaux de droits.
Un technicien n'aura pas les mêmes privilèges sur l'application que son supérieur hiérarchique. Ce dernier n'aura également pas les mêmes droits que le directeur des ressources humaines ou le PDG. Dans ce genre d'application, le mot de passe est le garant de la sécurité des données. Il faut donc le protéger assidument. Un recours au chiffrement devient alors indispensable.
Pourquoi crypter les données sensibles dans un SI ?
La réponse est simple. Il s'agit de garder confidentiel le mot de passe qui a été attribué à l'utilisateur en dehors de l'application. Il y'a aussi une part de déontologie dans la mesure où même le responsable de l'application ne devrait pas à connaître les identifiants personnels des utilisateurs. Cela ne le regarde pas. Revenons à notre exemple.
Qui dit extranet dit aussi accès à l'application depuis Internet. Il convient alors de chiffrer les données par une connexion sécurisée HTTPS et de protéger l'application contre d'éventuels accès pirates. Admettons que cet extranet ait mal été écrit et qu'il comporte une faille d'injection SQL. Un pirate pourrait alors récupérer les mots de passe enregistrés dans la base de données et pénétrer l'application sans problème avec les identifiants du PDG. Si les mots de passe sont cryptés, le pirate aura bien plus de mal à retrouver leur correspondance en clair. Dans cet exemple, l'attaque provient de l'extérieur mais qu'en est-il si la faiblesse du système se trouve à l'intérieur même de celui-ci ?
En effet, supposons qu'il faille maintenir la base de données en se connectant directement dessus. La société qui a édité l'application envoie son administrateur de base de données en intervention. Ce technicien intervient sur place mais ne fait aucunement partie de la société qui utilise l'application. Pourtant elle va manipuler la base de données. C'est à dire qu'elle pourra très probablement consulter tout ce qui s'y trouve à l'intérieur... y compris les identifiants de connexion. Si les mots de passe avaient été enregistrés en clair, il aurait pu s'approprier les accès de n'importe quel utilisateur sur l'application extranet... Malgré tout, rien ne l'empêche de se créer un nouvel utilisateur avec tous les droits directement dans la base de données. Nous verrons donc par la suite qu'un cryptage traditionnel ne suffit pas pour renforcer la sécurité d'un mot de passe.
Les méthodes de cryptage
Il en existe beaucoup. Cela peut aller des algorithmes de cryptage (pouvant être décryptés avec l'algorithme et la clé adéquate) aux algorithmes de hashage. Ce sont plutôt ces derniers que l'on a tendance à utiliser aujourd'hui. En effet, un algorithme de hashage permet de chiffrer une chaine sans possibilité d'opération inverse. Le résultat du hash produit généralement une chaine unique et de longueur fixe. C'est le cas par exemple des algorithmes MD5 et SHA1. Ainsi, lors d'une phase d'authentification, on ne compare plus deux mots de passe en clair mais deux hashes du mot de passe.
Hasher un mot de passe avec MD5
Exemple de hash avec md5()<?php?>
La variable $md5 contient alors une chaine unique, composée de caractères hexadécimaux et d'une longueur de 32 caractères.
Hasher un mot de passer avec SHA1
Exemple de hash avec sha1()<?php?>
La variable $sha1 contient ici une chaine unique, composée de caractères hexadécimaux et d'une longueur de 40 caractères.
Pourquoi les hashs simples ne suffisent plus ?
Cette méthode permet de chiffrer les chaines efficacement mais restent « crackables » ! « Ah bon ? Pourtant il a été écrit plus haut que l'on ne pouvait réaliser l'opération inverse !!! » Effectivement ! Néanmoins il existe sur Internet des « rainbow tables » (dictionnaires) capables de vous retourner la chaine en clair d'un md5(), d'un sha1() ou d'un autre algorithme standard de hash. Nul besoin de rappeler que les mots de passe classiques du type root, superadmin, toto... existent dans ces dictionnaires. Pour peu que le mot de passe original soit un mot du dictionnaire, il est fort probable que l'on puisse le retrouver dans une rainbow table à partir de son hash.
Hasher les mots de passe avec des « salts »
Cette technique consiste en la concaténation d'une ou plusieurs clés (appelées aussi « salt », « seed » ou « graine ») au mot de passe, puis le hashage de la chaine ainsi créée. Bien entendu, la / les clés doivent rester secrètes dans un fichier de configuration de l'application. Prenons un exemple simple de hash de mot de passe à partir de deux graines.
Hash de mot de passe avec des salts<?php// Déclaration des constantes?>
Dans cet exemple, nous allons finalement hasher avec l'algorithme MD5 la chaine suivante : prisonm0tD3P4ss3break
Ainsi le MD5 de cette chaine sera complètement différent du MD5 du mot de passe seul.
Quel est alors l'intérêt de cette technique ?
Cette technique permet de ne pas pouvoir récupérer facilement le mot de passe d'origine en clair dans une rainbow table à partir du MD5. La sécurité du mot de passe réside alors dans la complexité et la confidentialité des clés choisies.
Revenons à notre exemple de départ en considérant que les mots de passe sont cette fois-ci hashés avec cette méthode avant d'être enregistrés en base de données. Le technicien malintentionné en intervention sur la base de données pourra essayer de cracker les mots de passe à partir d'une rainbow table, il n'y parviendra pas car il ne connait pas les graines utilisées et la méthode de cryptage employée. De même, s'il reconnait le format MD5 des mots de passe et qu'il enregistre son mot de passe sous ce format, celui-ci ne fonctionnera pas au moment de l'identification. En effet, le hash de la concaténation de son mot de passe saisi et des deux graines ne correspondra pas au hash qu'il a enregistré juste avant dans la base de données.
Cette technique peut-elle servir en dehors des mots de passe ?
La réponse est oui ! Cette technique est employée pour chiffrer des informations placées dans un champ caché de formulaire ou bien dans un cookie. La technique du seed permet notamment de vérifier l'intégrité d'une donnée enregistrée entre chaque page. Cela revient à dire que si son hash ne correspond pas avec le hash attendu, c'est que le client a modifié l'information de son côté pour tenter de gruger votre application. Il sera donc possible d'appliquer les traitements adéquats : message d'erreur, bannissement de l'utilisateur pendant un certain temps...
Les commentaires
2. Par Emacs le lundi 14 janvier 2008 à 19:07
Merci Xireus pour le commentaire. Effectivement Crypt() permet en plus d'utiliser un salt en paramètre facultatif. Je vais songer à ajouter ça en plus au tutoriel.
3. Par chubie le samedi 02 février 2008 à 19:07
Un tutoriel très intéressant. Je connaissais md5 et sha1 mais pas la méthode des graines.
4. Par Divx le jeudi 07 février 2008 à 22:10
Il est vrai que le crypt() je l'utilise tout le temp je connaissai la technique des graines une technique peut rependut mais trés efficace !
5. Par Chrisvip le samedi 09 février 2008 à 22:10
Mais si tu mets "prison" et "break" dans le mot de passe, le MD5 change mais pas le mot de passe quand on l'entre ? C'est-à-dire quand je me connecte sur un espace membres...
6. Par Emacs le dimanche 10 février 2008 à 00:12
Je ne comprends pas où tu veux en venir. Les salts doivent obligatoirement restées secrètes et être concaténées à chaque fois que tu veux tester l'intégrité du mot de passe.
7. Par Huraken le lundi 11 février 2008 à 03:03
La comparaison du mot de passe se fera toujours avec la concaténation des graines et le md5 de la base de données, çà ne va pas changer le mot de passe de départ.
Sympa ce tutoriel, je connaissais pas les graines non plus.
8. Par Chrisvip le lundi 11 février 2008 à 18:06
Je sais si j'utilise ça dans un de mes sites, lorsque les membres vont taper leurs mots de passe, comment ils vont faire ?
9. Par Emacs le lundi 11 février 2008 à 21:09
Et bien lorsqu'ils tapent le password, tu concatènes les salts puis tu calcules le hash md5(). Il ne te reste plus qu'à le comparer avec celui enregistré en BDD. Si les deux hashes sont identiques, c'est que la concaténation des salts+PWD est identique et donc que le password tapé est correct.
10. Par Chrisvip le mardi 12 février 2008 à 20:08
Ah d'accord, mais on m'a dit que le MD5 est indécryptable, pourquoi utiliser ça alors ?
11. Par Emacs le mardi 12 février 2008 à 20:08
Tu n'as pas lu le tutoriel correctement. Certes md5() ne permet pas d'être décrypté. C'est le principe du hash. Mais il existe plusieurs solutions pour cracker un password en md5() comme par exemple :
* l'attaque par brute force qui va tester toute une série de combinaisons possibles jusqu'à trouver la bonne.
* l'utilisation du "rainbow table" (dictionnaire) qui va te retourner la correspondance en clair à partir d'une chaine md5(). Si le mot de passe et son md5 sont référencés dans une rainbow table, alors il n'y a plus de sécurité par rapport au password.
Avec la méthode du salt, ça permet de renforcer la sécurité des passwords car il devient plus difficile de retrouver la chaine originale.
En somme : La complexité de la salt + la complexité du password + la sécurité de la salt (connue de personne) = sécurité du password
12. Par Maxime le samedi 01 mars 2008 à 22:10
Tuto intéressant, mais j'ai une question à vous soumettre. Supposons qu'une personne à réussi à découvrir les mots de passe cryptés dans le système d'information avec une sécurité maximum. Supposons que pour vérifier le mot de passe des membres, le site utilise un système de cookie et qu'un cookie contient le mot de passe crypté du membre, au cas où celui-ci serait volé. Le mot de passe du cookie correspond donc au mot de passe du système d'information. Imaginons maintenant que la personne qui a réussi à découvrir les mots de passe dans le système d'information créé le cookie contenant le mot de passe des membres, qu'il y place le mot de passe d'un membre prélevé dans le système d'information, vous serez d'accord qu'il jouira des mêmes droits de celui de qui il a pris la place.
Comment parer ce problème ?
13. Par Paul Henri Bonnement le dimanche 02 mars 2008 à 00:12
Tutoriel sympa, première fois que je vois cette méthode des graines, et je dois avouer qu'elle me plait bien
Pourquoi ne pas pousser le vice en passant plusieurs algo de cryptage sur les mot de passe ? :o
14. Par Emacs le dimanche 02 mars 2008 à 00:12
@Maxime : pour parer ce problème c'est tout simple. Il y'a une règle d'or à respecter : ne jamais transmettre de mot de passe (même crypter) dans un cookie. Il vaut mieux y stocker une chaine cryptée qui a par exemple été construite avec la concaténation du login, email et chaine aléatoire au moment de l'inscription. Cette nouvelle chaine est placée dans le cookie et en base de données. Le problème c'est que malgré tout, si le pirate arrive à voler ce cookie, alors il pourra se logguer sur le compte de la personne. Donc la meilleure manière de se protéger à se niveau là est de ne pas implémenter de système de reconnaissance automatique et d'obliger l'utilisateur à se logguer à chaque passage. C'est certes moins ergonomique et "user-friendly" mais c'est aussi la méthode la plus "secure".
@Paul Henri : on pourrait très bien pousser le vice en multipliant les algorithmes de cryptage. Par exemple faire un sha1() sur un md5(). Il n'appartient qu'au développeur de choisir la stratégie de sécurité à appliquer à son application et à ses passwords. Cette méthode des salts avec un seul md5() ou sha1() s'avère déjà très efficace dans la mesure où les graines sont bien évidemment gardées secrètes.
15. Par Nicolas c'est moi le jeudi 03 avril 2008 à 16:04
En français, on dit chiffrer et pas crypter qui est un angliscisme.
Sinon le fait d'appliquer plusieurs algorithme de chiffrement successivement n'améliore pas la sécurité.
16. Par Emacs le jeudi 03 avril 2008 à 18:06
Oh Nicolas ! Merci pour ton passage et ton commentaire
Je note ta remarque concernant l'abus de langage. Je vais mettre l'article à jour.
Par contre, pourrais-tu nous expliquer pourquoi le fait d'appliquer plusieurs algorithmes de chiffrement n'améliore pas la sécurité stp ? Serait-ce parceque ça renforce les risques de collision ?
17. Par dinette le jeudi 10 avril 2008 à 20:08
Tuto très sympa et fort intéressant mais ce qui m'intrigue, c'est que si le membre perd son mot de passe comment le récupérer et le lui renvoyer? Moi cela m'est déjà arrivé plusieurs fois. Il est crypté dans la db donc irrécupérable.
18. Par Emacs le jeudi 10 avril 2008 à 21:09
Bonsoir Dinette,
On ne renvoie pas le password d'origine puisque l'on ne peut pas le retrouver. Dans ce cas, on est obligé de générer un nouveau password et de l'envoyer à l'utilisateur pour qu'il puisse se relogguer et le changer.
19. Par pagesdiv le samedi 03 mai 2008 à 12:12
Crypt est une racine grecque tres ancienne signifiant caché.
Donc NE FAIT ABSOLUMENT PAS partie du patrimoine parlé celte/saxon.
Crypter n'est donc pas un anglicisme. C'est une appropriation historique.


1. Par Xireus le lundi 14 janvier 2008 à 19:07