Convertir les mots de passe en clair en mots de passe SHA-1 dans un serveur LDAP avec JMeter

Voici un complément à ce premier tutoriel sur JMeter et un serveur LDAP, où les mots de passe qui ont été insérés dans le serveur LDAP l’ont été en clairs. C’est à dire que si vous disposez d’un accès au serveur LDAP (et/ou que le serveur LDAP a une configuration pas très sécurisée) vous pouvez voir les mots de passe en clair de tout le monde. Ah, ce n’est pas terrible, pas de problème, reprenons JMeter pour effectuer une conversion en SHA-1 des mots de passe.

(Attention cela n’empêche pas de mieux sécuriser son serveur LDAP pour par exemple interdire la consultation du champ du mot de passe dans le LDAP par tout autre utilisateur que lui-même)

Les objectifs de ce nouveau tutoriel sont :

  • Montrer comment parcourir les enregistrements d’un LDAP avec JMeter
    • Pour cela avec un contrôleur Pour chaque
  • Faire une action conditionnelle avec un contrôleur Si, en fonction d’une valeur de variable
  • Monter la manipulation de données (variables JMeter) dans une utilisation avec Pré-processeur BeanShell

La capture suivante l’arbre JMeter de ce tutoriel.

On commence bien entendu par ajouter un élément Groupes d’unités (en 1-1-1) pour permettre par la suite l’exécution du scénario. Ensuite on attaque avec l’ajout de la première Requête LDAP étendue, elle va se charger de la connexion avec le serveur LDAP.

Le type de test est « Unité liée » (bind en anglais) correspondant à une connexion sur le serveur LDAP.

On complète les champs suivants :

  • Nom du serveur, par le nom ou l’adresse IP du serveur LDAP
  • Port, en général le port 389
  • DN : nom du suffixe d’annuaire
  • Identifiant, par le « login » de connexion à l’annuaire LDAP.
  • Mot de passe associé

La requête LDAP suivante va permettre de faire la recherche dans le LDAP de la liste des utilisateurs. On sélectionne le périmètre de recherche au niveau du champ Search base, en indiquant « ou=Users » (qui sera suffixé par dn=milamberspace,dn=net), le filtre de recherche (Search Filter) est « (uid=*) », où l’étoile indique « tous ». Cette requête LDAP signifie donc : « On cherche toutes les fiches de l’annuaire du groupe d’utilisateurs ou=Users,dn=milamberspace,dn=net. »

L’extracteur d’expression régulière, ajouté en tant que fils de la requête LDAP de sélection des fiches utilisateurs, va permettre de créer une grande liste des UID (identifiants des utilisateurs) provenant des résultats de recherche. La RegExp va créer un ensemble de variables JMeter ayant le format suivant « VAR_UID_xx » où xx correspond à un indice de liste.
On note que c’est la valeur « -1 » dans le champ « Correspond au num. » qui permet d’indiquer à JMeter qu’il faut créer une liste de variables VAR_UID_xx pour toutes les occurrences trouvées avec l’expression régulière.

Histoire de vous aider à matérialiser la chose, la capture suivante montre les fameuses variables VAR_UID_xx qui vont être créées lors de l’exécution.

On reviens aux éléments du scénario avec le contrôleur Pour chaque :

Ce contrôleur Pour chaque qui va permettre de parcourir la liste des variables VAR_UID_xx récupérées dans la requête précédente. Pour chaque valeur de variable, on va faire le traitement suivant :

  1. Une requête LDAP de recherche pour récupérer le mot de passe en clair
  2. Si besoin, une requête LDAP de mise à jour afin de remplacement ce mot de passe par sa version SHA-1 (empreinte SHA)
  3. Si besoin, une requête LDAP de recherche pour s’assurer que la mise à jour s’est bien passée.

Donc pour la requête de recherche du mot de passe d’un utilisateur donné, on va remplacer l’étoile dans le champ Search Filter par la valeur de la variable ${UID} qui correspondra à l’utilisateur courant dans la boucle Pour chaque.

Le champ Size Limit sera placé à 1 (on ne cherche que 1 seul élément. Enfin c’est pas vraiment obligatoire de remplir ce champ, on est censé toujours avoir 1 élément en retour). On place la limite de temps de réponse à 10 000 ms, et surtout on place « userPassword » dans le champ Attributes afin que le serveur LDAP nous revoie seulement la valeur de ce champ pour l’utilisateur.

On n’oubliera pas de cocher la case « Examiner les résultats de recherche ? » afin de l’on puisse avoir, dans les données de réponses, les valeurs demandées (ici le userPassword).

Ensuite, commence une série de trois extracteurs d’expression régulière. Le premier va permettre la récupération du mot de passe, ce dernier se situe entre deux balises userPassword dans la réponse.

La deuxième est pour récupérer l’identifiant de l’utilisateur en cours. Ce n’est pas obligatoire, mais cela permet de vérifier si on a eut le bon utilisateur.

La troisième est pour récupérer le mot de passe au format SHA dans le cas où l’utilisateur a déjà un mot de passe au format SHA. Donc cela voudra dire qu’il ne faut pas convertir son mot de passe.

Le contrôleur Si va justement permettre de déterminer si c’est nécessaire ou non de faire la conversion. Pour cela on compare si la variable cible de l‘extracteur d’expression régulière MOT_DE_PASSE_SHA a reçu la valeur par défaut (ici il s’agit d’un texte arbitraire qui est stocké dans la variable ${MDP_NON_SHA}).

Donc si c’est la valeur par défaut, c’est que le mot de passe n’est pas en SHA, il convient donc de procéder à la conversion.

Cette requête LDAP est donc celle de la modification. On choisi le type de test « Modification test », et dans le tableau, on définit l’attribut userPassword, sa nouvelle valeur (voir ci-dessous) et le code d’opération « replace ».

Le Pré-Processeur BeanShell est rattaché en tant que fils à la requête LDAP de modification. C’est lui qui va faire la conversion du mot de passe en clair vers un mot de passe en SHA, le tout en code de programmation Java. Il permet donc de créer (définir) la nouvelle valeur du mot de passe qui sera insérée par la requête de modification.

La requête suivante est pour faire une nouvelle recherche de l’utilisateur courant. On va, en effet, re-demander son mot de passe afin de vérifier qu’il a bien été changé.

La vérification du bon changement, est assurée par un élément Assertion Réponse. Le motif à tester est le nouveau mot de passe (le SHA), et attention, le type de correspondance est « Commence par ». La traduction en français induit en erreur, car en fait, cela « ne commence pas par » mais plutôt « Contient (sans expression régulière) », car dans le nouveau mot de passe, il peut y avoir des caractères spéciaux d’expressions régulières qui risquent d’être mal interprétés avec le type « Contient ». (je vais proposer une nouvelle traduction pour la prochaine version de JMeter)

La dernière requête LDAP est celle de la déconnexion (Délier les unités).

Et voilà, il ne reste plus qu’à faire une exécution du test (une et une seule), tout en vérifiant dans l’arbre de résultat que tout s’est bien passé.

Le récepteur d’Assertion, dans l’arbre JMeter, permettra, quant à lui de capter d’éventuels problèmes lors de l’exécution. Il est préférable de cocher la case « Uniquement (les) Erreurs » dans ce récepteur, afin de ne voir que les problèmes survenus.

Voilà pour ce deuxième billet sur JMeter et les LDAP. Bon courage.

./