Sécuriser les mots de passe avec les hashs et les salts

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
$md5 = md5('m0tD3P4ss3');
?>

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
$sha1 = sha1('m0tD3P4ss3');
?>

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
define('PREFIX_SALT', 'prison');
define('SUFFIX_SALT', 'break');
 
$hashSecure = md5(PREFIX_SALT.'m0tD3P4ss3'.SUFFIX_SALT);
?>

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...