Introduction à LemonLDAP::NG

LemonLDAP::NG est un serveur d’authentification web open source développé initialement par la Gendarmerie Nationale.
En premier lieu, LemonLDAP::NG est conçu comme un fournisseur d’identité. Il est donc compatible avec les standards SAML, OpenID Connect et CAS. Pour chacun d’eux, LemonLDAP::NG peut opérer comme un fournisseur d’identité mais également comme un fournisseur de service dans certains cas (notamment pour gérer l’authentification par rebond).
En tant que fournisseur d’identité, le produit réalise directement les authentifications des utilisateurs. Pour cela, de nombreux modes d’authentification sont supportés tels que : LDAP, Active Directory, Kerberos, Radius etc.
A tout cela s’ajoute le support de la 2FA et des différents types de second facteur : FIDO2 (WebAuthn), U2F, TOTP, Yubikey, OTP par mail ou SMS, entre autres.

Niveaux d’authentification et 2FA

La raison d’implémenter la 2FA est toujours la même : augmenter le niveau de sécurité associé à l’authentification.
C’est pourquoi chaque mode d’authentification et chaque type de second facteur se voit associer un niveau d’authentification, plus ou moins élevé, lors de sa configuration dans LemonLDAP::NG.
Par exemple, une clé FIDO2 aura un niveau 4 quand un envoi d’OTP par mail sera affecté à un niveau 3. L’authentification par mot de passe sera quant à elle reléguée à un modeste niveau 1 voire 2 selon le contexte.

niveau d'authentification pour module LDAP

Exemple de configuration : niveau d’authentification pour module LDAP.


Mais avec l’utilisation de la 2FA vient la problématique de l’enrôlement du facteur. Et par extension, celle de la perte de celui-ci et de son désenrôlement.

Scénario d’authentification forte

Prenons l’exemple d’une utilisatrice, Alice, ayant régulièrement besoin d’accéder à un service XYZ exposant des données sensibles. Alice s’authentifie à ce service par l’intermédiaire de LemonLDAP::NG qui agit en tant que fournisseur d’identité.
Dans ce cas, l’accès au service XYZ requiert évidemment l’emploi des classiques login et mot de passe. L’authentification doit cependant être complétée par une authentification 2FA par clé FIDO2 avec saisie de code pin.
Pourquoi cela ? Parce que le fournisseur de service XYZ défini dans LemonLDAP::NG requiert un niveau d’authentification plus élevé que celui défini pour l’authentification par mot de passe seule.

Que faire en cas de perte d’un 2FA ?

Prenons l’hypothèse que ladite clé soit volée par une personne malveillante, Bob. Il faudrait alors que Bob ait connaissance du mot de passe d’Alice et du code pin nécessaire à l’utilisation de la clé pour pouvoir usurper son identité.
Dans cette hypothèse, le niveau de sécurité est ramené à celui du mot de passe d’Alice. Le code pin de la clé étant plus aisément obtenable, Bob va pouvoir utiliser la clé et essayer de le deviner. Et même si son usage est limité à 8 essais infructueux, mieux vaut ne pas jouer avec le feu.
La réponse à apporter est simple : il faut désenrôler la clé d’Alice afin de s’assurer qu’elle ne puisse pas être utilisée de manière frauduleuse.

Le plugin ContextSwitching

Malheureusement, Alice ne peut pas désenrôler sa clé dans l’interface de gestion 2FA de LemonLDAP::NG. Cela requiert un niveau d’authentification au moins égal à celui du second facteur à supprimer. Et dans la cas présent, cela implique qu’Alice s’authentifie avec sa clé, alors qu’elle l’a justement perdue !

Interface de gestion 2FA de LemonLDAP::NG

Interface de gestion 2FA de LemonLDAP::NG. L’action « Supprimer » nécessite l’authentification avec un niveau équivalent.

Nous pourrions donc imaginer que cette opération de désenrôlement puisse être exécutée par un administrateur. C’est ici que cela se complique : par défaut ce n’est pas possible, seule Alice peut gérer sa propre clé dans LemonLDAP::NG.
Il existe toutefois une solution : le plugin ContextSwitching. Celui-ci offre la possibilité à un utilisateur privilégié d’endosser l’identité d’un autre et, dans le cas qui nous intéresse, d’accéder à la gestion des seconds facteurs de ce dernier.
Une fois le plugin et ses règles d’accès configurées (il s’agit ici de spécifier qui peut endosser l’identité de qui), un administrateur Charlie pourra se connecter en s’authentifiant avec sa propre clé FIDO2, endosser l’identité d’Alice et désenrôler la clé disparue.

Le problème de l’endossement d’identité

Revenons à l’exemple initial : Alice accède au service XYZ par l’intermédiaire de LemonLDAP::NG. En endossant son identité, Charlie le peut également, quand bien même il n’aurait pas accès personnellement à ce service.
Et dans le cas où Charlie dispose de son propre accès, le problème demeure puisque cela lui permet de se connecter en tant qu’Alice et donc d’hériter de ses droits.
Les options de configuration du plugin ContextSwitching ne permettent pas de restreindre le périmètre dans lequel une identité empruntée peut agir… Hormis pour la gestion des 2FA, ce qui est justement la raison de l’utiliser ici !
Retirer la possibilité à Charlie d’usurper l’identité d’Alice pour accéder au service XYZ est impératif. Il est donc nécessaire d’empêcher l’accès à XYZ lors d’un emprunt d’identité. Pour ce faire, il va falloir détecter ce type de session.

La piste des variables de session

Lorsque Charlie se connecte sur LemonLDAP::NG, une session est créée avec une multitude de variables, dont les attributs l’identifiant : on retrouve l’uid en cas d’authentification LDAP par exemple.
Lorsque Charlie endosse l’identité d’Alice, la première session est maintenue et une seconde session est créée. Celle-ci correspond à la session qu’aurait ouverte Alice elle-même mais diffère en structure sur un point : elle se réfère à la session de Charlie via la variable switching_session_id.
Visualisation de la session d'Alice empruntée par CharlieVisualisation de la session d’Alice empruntée par Charlie.


Reste à savoir comment l’exploiter…

Solution : ajouter une règle d’accès !

Nous avons vu que LemonLDAP::NG gère l’accès aux services et applications à l’aide de niveaux d’authentification dédiés. Ce n’est heureusement pas le seul moyen de contrôler l’accès : il est possible de définir des règles d’accès écrites en langage Perl.
Il est alors aisé de contrôler l’accès au service XYZ en associant au fournisseur de service XYZ, déclaré dans LemonLDAP::NG, une règle d’accès contrôlant l’existence de la variable citée auparavant.
Cela nous donne la règle suivante : $switching_session_id eq undef

niveau d'authentification associé à l'accès au service

La règle telle qu’elle apparaît dans l’interface de LemonLDAP::NG. Notez le niveau d’authentification associé à l’accès au service.


L’accès à XYZ n’est alors autorisé que si la variable switching_session_id n’existe pas : ce n’est possible que pour un accès primaire et non pour un accès via endossement d’identité.
Avec cette règle, Charlie ne peut plus accéder au service XYZ en endossant l’identité d’Alice, puisque cela entraîne l’existence de la variable switching_session_id.

Message d'erreur généré lors de la tentative d'accès à XYZ avec une session empruntée Message d’erreur généré lors de la tentative d’accès à XYZ avec une session empruntée.


Conclusion

La possibilité de définir des règles d’accès en Perl est une fonctionnalité très puissante de LemonLDAP::NG.
Avec la règle définie dans notre scénario, plus personne ne peut se connecter à XYZ avec une identité empruntée. Nous avons donc l’assurance que n’accèdent au service XYZ que les personnes effectivement authentifiées.
Mais l’endossement d’identité reste possible pour les applications où cela est nécessaire, et en particulier pour le désenrôlement des clés 2FA. La problématique initiale, à savoir la gestion de la perte d’un 2FA, est donc bien traitée !

Auteur : Romain (Consultant confirmé identité et accès)