Le password spraying, c’est une technique connue qui consiste à tester un même mot de passe sur plusieurs comptes, en espérant que ce mot de passe fonctionne pour l’un d’entre eux.

Cette technique est utilisée dans beaucoup de cadres différents : Sur des applications web, du cloud, des services comme SSH, FTP, et bien d’autres. On l’utilise également beaucoup dans des tests d’intrusion au sein d’entreprises utilisant Active Directory.

C’est à ce dernier cas que nous allons nous intéresser, parce que bien que la technique paraisse simple, ce n’est pas évident de la mettre en pratique sans effets de bord.

Introduction

Cet article n’est pas une découverte révolutionnaire, mais plutôt un état de mes recherches sur les politiques de mots de passe dans un environnement Active Directory. En effet, il existe plusieurs moyens de limiter les tentatives d’un attaquant via le blocage de comptes. Ces différents leviers sont très utiles lorsqu’ils sont compris, ce qui n’est pas toujours le cas (et ce n’était pas mon cas il y a quelques semaines).

Cet article permettra, je l’espère, de clarifier ce que permettent les politiques de mot de passe, comment elles sont appliquées, et donc en tant que pentester, comment faire du password spraying en réduisant au mieux les risques de blocage de comptes.

Mécanisme d’authentification

Le password spraying sur un annuaire Active Directory consiste donc à choisir un mot de passe qu’on considère comme très probablement utilisé par au moins un utilisateur, et on le teste sur l’ensemble des utilisateurs du domaine. On ne détaillera pas ici les moyens existants pour tester la validité d’un mot de passe, il en existe beaucoup. Un mot de passe peut être testé via Kerberos ou NTLM, quel que soit le protocole utilisé (SMB, LDAP, …).

Quoiqu’il en soit, lorsque l’authentification est testée, le contrôleur de domaine vérifiera d’abord si le compte est verrouillé par la politique de mots de passe. Le cas contraire, il vérifiera la validité du mot de passe. Enfin, si le mot de passe est valide, le compte sera authentifié, et l’attribut LDAP badPwdCount de l’utilisateur sera remis à 0. Si en revanche le mot de passe est erroné, alors badPwdCount sera incrémenté, et si cet échec entraine un verrouillage du compte, en suivant les critères des politiques de mots de passe, alors le compte sera marqué comme verrouillé. Cela est fait en renseignant la date et l’heure courante dans l’attribut LDAP lockoutTime de l’utilisateur.

Ca fait déjà un sacré processus de vérification, que j’ai tenté de résumer dans un schéma. Est-ce que ça clarifie les choses ? Je n’en suis pas sûr. Mais le voilà quand même.

Processus de vérification de mot de passe

Processus de vérification de mot de passe

Maintenant qu’on a clarifié cette logique, on comprend qu’il reste une inconnue qui semble plutôt importante, c’est la politique de mot de passe. Parce qu’en effet, c’est en suivant la politique de mot de passe appliquée au compte que le contrôleur de domaine est capable de savoir si oui ou non, le compte est verrouillé, ou s’il doit l’être. Voyons alors où se trouve cette politique par défaut, et détaillons les paramètres qui nous intéressent.

La politique de mots de passe par défaut

Lorsqu’on installe un Active Directory, il y a beaucoup de choses qui sont créées et paramétrées par défaut. Parmi elles se trouvent deux GPO : La Default Domain Policy liée à la racine du domaine, et la Default Domain Controller Policy liée à l’OU Domain Controllers.

Dans la Default Domain Policy, on trouve les paramètres suivants qui permettent de définir les règles de verrouillage des comptes.

Politique de mots de passe par défaut

Politique de mots de passe par défaut

  • Account lockout duration : Lorsqu’un compte est verrouillé suite à un mot de passe erroné, ce paramètre définit le temps durant lequel ce compte reste verrouillé.
  • Account lockout threshold : Détermine le nombre de tentatives erronées autorisées. Si ce paramètre est 3, alors 3 tentatives erronées verrouilleront le compte.
  • Allow Administrator account lockout : Quand ce paramètre est activé, cela signifie que même le compte d’administration par défaut (Administrator) est concerné par la politique de mots de passe.
  • Reset account lockout counter after : En règle générale, lorsqu’une authentification échoue, badPwdCount est incrémenté. Cependant, si la tentative échouée précédente est plus ancienne que le temps paramétré ici, alors badPwdCount est remis à 0. Par exemple, si ce paramètre vaut 5 minutes alors lors d’un premier échec, badPwdCount vaut 1. Lors d’un 2ème échec quelques secondes après, badPwdCount vaut 2. Si un 3ème échec survient, mais 5min10 après le 2ème échec, badPwdCount aura été réinitialisé à 0, et cet échec le passe donc à 1.

Voilà les fameux paramètres qui sont pris en compte par le contrôleur de domaine pour savoir si un compte est verrouillé. Concrètement (et parce que le schéma précédent n’était pas assez complexe bien sûr), ces valeurs sont utilisées de la manière suivante :

Processus complet de vérification d'un mot de passe

Processus complet de vérification d’un mot de passe

Vous voyez donc que pour savoir si le compteur de mauvais mot de passe est calculé en prenant la date du dernier échec, et si le temps définit dans Reset account lockout counter after est passé, alors le compteur est remis à zéro. Sinon, il est incrémenté. Ce compteur est alors comparé à Account lockout threshold. Si c’est égal (ou supérieur), alors le compte est considéré comme verrouillé, et le champ lockoutTime est rempli. Lors d’une prochaine tentative, si le temps définit dans Account lockout duration est passé (en prenant comme départ la date dans lockoutTime) alors le compte n’est plus verrouillé, et le mot de passe va être testé.

Si ce n’est toujours pas clair, alors reprenez ces explications depuis le début, et concentrez-vous. Je ne saurai pas mieux expliquer. Il faut que tout ça soit clair pour comprendre la suite. En effet, on a parlé de la politique de mot de passe dans la GPO Default Domain Policy. Mais on va voir qu’il n’y a pas qu’ici que cette politique peut être définie.

Ordre d’application des GPO

Personnellement, j’aime bien créer une nouvelle GPO à chaque fois que je veux apporter une modification à mon système d’information. Ainsi, pour appliquer une politique de mots de passe, je créerai une GPO dédiée, dans laquelle il n’y aura que des paramètres liés à la politique de mot de passe, et ça fonctionnera très bien. En effet, on a vu que les paramètres étaient présents dans la Default Domain Policy, mais ils peuvent évidemment être paramétrés dans n’importe quelle GPO.

Ce qui est intéressant à savoir, c’est le comportement suivi quand cette politique de mots de passe est définie dans plusieurs GPO à la racine du domaine.

Il existe en fait un ordre de priorité qui permet de définir quelle GPO prend le dessus en cas de conflit. Dans le gestionnaire de GPO, lorsque vous cliquez sur une OU (ou sur le domaine), vous avez la liste des GPO appliquées dans l’onglet Linked Group Policy Objects. Vous remarquerez qu’elles sont numérotées, via la colonne Link Order, ce qui permet de déterminer la priorité de chaque GPO. Concrètement, la dernière GPO de la liste sera d’abord appliquée, puis l’avant dernière, jusqu’à la GPO numéro 1. Ainsi, c’est la GPO numéro 1 qui aura “le dernier mot”. Si elle avait des paramètres qui entraient en conflit avec les autres GPO, ce seront ses paramètres à elle qui seront effectifs.

Ordre des GPOs

Ordre des GPO

Dans cet exemple, si jamais une politique de mot de passe est définie dans PASSWORD POLICY et une autre dans Default Domain Policy, c’est cette dernière qui sera réellement appliquée.

Il n’y a pas d’attribut qui permet d’avoir le numéro de la GPO dans la liste. En fait, pour chaque unité organisationnelle (et pour l’objet domaine), l’attribut gpLink contient la liste des GPO qui sont liées à cet objet, et elles sont enregistrées dans l’ordre d’application, donc dans l’ordre décroissant de Link Order. Sur l’objet hackn.lab, on trouvera dans cet exemple d’abord la GPO PASSWORD POLICY, puis LOCKSCREENFIREWALL et enfin Default Domain Policy.

Bien, en listant les GPO qui sont appliquées à la racine du domaine, on est maintenant capable de savoir quelle est la véritable politique de mots de passe appliquée par ce biais.

Mais évidemment, ça ne s’arrête pas là. Comment faire si on souhaite appliquer une politique de mots de passe différente pour nos administrateurs par exemple ? Et oui, on impose une politique à nos utilisateurs, mais on souhaiterait une politique plus forte pour nos administrateurs, et c’est une très bonne pratique !

Politique de mots de passe sur une unité organisationnelle

Avant même de commencer ce chapitre, j’annonce que ça ne fonctionnera pas. Il faudra utiliser des PSO pour atteindre cet objectif, ce qu’on verra juste après.

En effet, nous pourrions être tentés par organiser notre Active Directory de telle sorte à ce que nos administrateurs soient dans une unité organisationnelle dédiée, et nous voudrions appliquer une politique de mot de passe spécifique à ces utilisateurs. Pourquoi ne pas créer une GPO dédiée à cette OU, dans laquelle nous définissons nos critères bien robustes de mots de passe sécurisés ?

Prenons cet exemple. Nous avons une GPO PASSWORD POLICY placée à la racine du domaine, qui autorise de se tromper 10 fois avant verrouillage pendant 10 minutes.

Détails de la politique PASSWORD POLICY

Détails de la politique PASSWORD POLICY

Créons alors une GPO beaucoup plus robuste liée à l’OU Admins dans laquelle se trouve le compte adm_pixis. Cette GPO devrait bloquer un compte après 2 tentatives échouées, et le compte devrait être bloqué pendant 60 minutes.

Détails de la politique SUPER STRICT PASSWORD POLICY

Détails de la politique SUPER STRICT PASSWORD POLICY

Maintenant, nous pouvons essayer de nous connecter avec l’utilisateur adm_pixis, mais nous nous trompons volontairement de mot de passe. Une fois, deux fois, … trois fois, quatre fois. Le compte n’est toujours pas verrouillé.

Compte non verrouillé après 3 essais

Compte non verrouillé après 3 essais

En revanche, lors du 11ème essai, ça ne rate pas, notre compte est bien verrouillé.

Compte verrouillé après 10 essais

Compte verrouillé après 10 essais

Pourquoi cette magie noire ? Et bien tout simplement parce que ces paramètres qu’on définit par GPO, ils ont pour effet de mettre à jour certains attributs de l’objet auquel ils sont liés, et ces fameux attributs n’existent que sur l’objet domaine, pas sur les unités organisationnelles.

Attributs LDAP sur l'objet domaine

Attributs LDAP sur l’objet domaine

Vous avez ici l’attribut lockoutDuration qui correspond au paramètre Account lockout durationlockoutObservationWindow paramétré par Reset account lockout counter after, ou encore lockoutThreshold qu’on peut définir avec Account lockout threshold. Ainsi, lorsqu’une politique de mot de passe est définie par GPO liée à une OU, cette politique n’aura aucun effet sur cette unité organisationnelle, donc aucun effet sur les comptes du domaine dans cette OU.

Sachez que si vous appliquez une GPO avec une politique de mots de passe à un OU qui contient des ordinateurs (postes de travail ou serveurs), c’est sans effet sur le domaine, mais pas sur les machines, puisque la politique de mot de passe s’appliquera pour les comptes locaux.

Tout cela signifie alors qu’il semble uniquement possible d’appliquer une politique de mots de passe globale à tous les utilisateurs. Mais comment fait-on pour durcir cette politique pour nos administrateurs ? C’est pour répondre à ce besoin qu’entrent en jeu les PSO, ou Password Settings Objects.

Les PSO

Ah, les PSO. Voici la réponse à nos problèmes (pour de vrai). Ce sont des objets Active Directory qui permettent de définir les mêmes paramètres sur les mots de passe que ceux qu’on trouve dans les GPO, et de les appliquer à des utilisateurs, ou des groupes d’utilisateurs. On est donc en mesure de créer des politiques de mots de passe avec une granularité fine, ou Fine-Grained Password Policies (FGPP).

Ces objets doivent être créés à un endroit bien particulier, dans un conteneur qui s’appelle Password Settings Container, lui-même dans le conteneur System se trouvant à la racine du domaine. Une manière simple de créer des PSO est de passer par l’outil Active Directory Administrative Center et de naviguer dans ce conteneur.

Active Directory Administrative Center

Active Directory Administrative Center

Depuis cette interface, vous pourrez aisément créer des politiques de mots de passe et décider à qui ces politiques doivent s’appliquer. Si on voulait par exemple reprendre notre super politique sécurisée, on pourrait créer une PSO avec ces mêmes paramètres et l’appliquer à tous les membres du groupe Domain Admins.

PSO pour les admins du domaine

PSO pour les admins du domaine

La même question de priorité que les GPO se pose alors. Déjà, les PSO sont prioritaires par rapport à la politique de mot de passe du domaine. Ensuite, si plusieurs PSO sont créées, et que des utilisateurs sont concernés par différentes PSO, laquelle sera prise en compte ?

C’est le paramètre Precedence présent dans la PSO, juste après son nom, qui permet de trier les PSO par ordre de priorité. Tout comme le Link Order pour les GPO, les PSO sont appliquées de la Precedence la plus haute à la plus basse. Ainsi, les valeurs les plus basses sont prioritaires par rapport aux plus hautes, puisqu’elles ont également le dernier mot.

Si jamais deux PSO ont la même valeur dans Precedence, c’est la dernière PSO créée qui sera prioritaire

Descendons un tout petit peu plus dans la technique. On a vu que lorsque des GPO paramètrent la politique de mot de passe, leur ordre de priorité sera suivi et les attributs de l’objet domaine seront mis à jour pour refléter la politique de mots de passe effective. Ces attributs sont accessibles en lecture à tous les utilisateurs authentifiés, donc il suffit d’aller lire ces attributs sur le domaine pour connaitre la politique de mots de passe appliquée au domaine.

Qu’en est-il des PSO ? Comment savoir si un utilisateur est affecté par telle ou telle PSO ? Les PSO ne peuvent pas modifier les attributs du domaine, puisque par nature, elles sont là pour avoir des politiques de mots de passe différentes. En fait, chaque PSO étant un objet Active Directory, les politiques de mots de passe sont enregistrées dans les attributs de leur objet.

Politique de mots de passe dans les attributs LDAP de la PSO

Politique de mots de passe dans les attributs LDAP de la PSO

Les attributs n’ont pas exactement le même nom que sur le domaine, ça serait trop simple, mais on s’y retrouve quand même. Toujours dans notre objectif de password spraying, on sera notamment intéressés par msDS-LockoutThreshold et msDS-LockoutObservationWindow.

Un autre attribut qui nous intéresse fortement est msDS-PSOAppliesTo. Il contient la liste des utilisateurs et/ou groupes auxquels s’applique la PSO.

Attribut msDS-PSOAppliesTo correspondant à la liste des utilisateurs et groupes sur lesquels s'applique la PSO

Attribut msDS-PSOAppliesTo correspondant à la liste des utilisateurs et groupes sur lesquels s’applique la PSO

Problème de droits sur le conteneur des PSO

On pourrait alors penser qu’à ce stade, nous avons tous les éléments en main pour connaitre la politique de mot de passe effective appliquée à chaque utilisateur.

Par défaut, on prend par défaut, pour chaque utilisateur, la politique de mot de passe du domaine en regardant les attributs sur l’objet domaine. Ensuite on liste toutes les PSO, qu’on analyse dans le bon ordre de priorité, on liste les utilisateurs dans les groupes sur lesquels sont appliqués chaque PSO, et on peut ainsi déduire pour chaque utilisateur la PSO qui est appliquée, et donc sa politique de mots de passe.

En théorie, ça fonctionnerait, mais il y a un petit hic dans cette démarche.

Droits sur le conteneur des PSO

Droits sur le conteneur des PSO

Vous voyez le problème ? Non ? Par défaut, seuls les administrateurs ont le droit de lister les PSO, ainsi que voir leur contenu. Ainsi, en tant qu’utilisateur lambda, on n’a aucun moyen de lister le contenu du conteneur Password Settings Container, et donc de voir les PSO, les politiques appliquées, et à qui elles sont appliquées.

Dans notre optique de password spraying, c’est assez dangereux. Ca signifie qu’on ne peut jamais être certain d’avoir les politiques de mot de passe effectives sur les différents utilisateurs du domaine, puisqu’on n’est pas à l’abri qu’une PSO (qu’on ne peut pas voir ni lire), s’applique sur un ou plusieurs utilisateurs.

Constructed Attributes & Backlinks

C’est en faisant face à ce mur que j’ai découvert les attributs construits, ou constructed attributes. Vous savez sûrement que quand on ajoute un utilisateur dans un groupe, l’attribut LDAP member du groupe est mis à jour, en ajoutant l’utilisateur. Si on liste simplement les attributs d’un utilisateur, on ne voit en revanche pas d’attribut memberOf.

Absence de memberOf

Absence de memberOf

En fait, il existe beaucoup d’autres attributs que ceux qu’on voit par défaut, mais ils sont gérés automatiquement par Active Directory. On ne peut pas les modifier manuellement. Ce sont des attributs construits à partir d’autres attributs, les fameux constructed attributes. Et parmi eux, une classe d’attributs s’appelle les backlinks. Ce sont des attributs qui vont de pair avec un vrai attribut, sur le même objet ou sur d’autres objets.

Comment voir les attributs back-links

Comment voir les attributs backlinks

Par exemple, l’attribut memberOf est un backlink qui va de pair avec l’attribut member. Ainsi, dès que l’attribut member d’un objet est modifié (ajout ou suppression d’un utilisateur ou d’un groupe), ce changement est automatiquement reflété dans sa paire, memberOf, de l’objet concerné. Donc si on affiche ces backlinks, on peut voir la liste des groupes auxquels appartient un utilisateur.

Attribut backlink "memberOf"

Attribut backlink « memberOf »

Et bien devinez quoi, il existe la même chose pour les PSO. On n’a pas le droit de lister les PSO avec un utilisateur standard, donc on ne peut pas lire l’attribut msDS-PSOAppliesTo présent sur chaque PSO.

Mais on a de la chance, il existe un constructed link pour cet attribut, et il s’appelle msDS-ResultantPSO. Alors lui, c’est pas un simple backlink, parce qu’il est un peu plus intelligent. Tous les utilisateurs du domaine ont cet attribut qui est potentiellement mis à jour à chaque fois qu’une PSO est appliquée à des utilisateurs, mais aussi à des groupes. Si un groupe est ajouté dans une PSO, tous les membres de ce groupe auront leur attribut msDS-ResultantPSO qui sera mis à jour, sous réserve que la PSO soit prioritaire. Donc en plus de dynamiquement résoudre les membres des groupes, cet attribut contiendra toujours le nom de la PSO effective qui s’applique à chaque utilisateur.

Et la cerise sur le gâteau dans tout ça, c’est que cet attribut, on peut le lire sur tous les utilisateurs du domaine, même avec un compte sans privilège.

Vous vous souvenez, on a appliqué une PSO au groupe Domain Admins. Allons regarder les attributs de type constructed du compte adm_pixis, qui fait partie de ce groupe.

Attribut construit "msDS-ResultantPSO"

Attribut construit « msDS-ResultantPSO »

On voit bien notre back-link memberOf qui contient Domain Admins, ainsi que notre attribut construit msDS-ResultantPSO dans lequel on retrouve la PSO que nous avons créée, et appliquée au groupe Domain Admins.

C’est parfait, maintenant on est capable de savoir si la politique de mots de passe d’un utilisateur est affectée ou non par une PSO.

Alors attention, on n’a toujours pas le droit de lire le contenu de la PSO, du moins pas en tant qu’utilisateur standard. Mais d’un point de vue password spraying, rien que savoir qu’une PSO est appliquée sur un utilisateur est extrêmement précieux. On peut tout simplement ignorer tous les comptes pour lesquels une PSO est appliquée, et restreindre nos tests aux utilisateurs pour lesquels la politique de mot de passe effective est celle du domaine.

Outillage

C’est en écrivant un outil de password spraying que j’ai suivi ce lapin blanc des politiques de mot de passe pour tenter de réduire au maximum le risque de verrouiller des comptes lors de mes tests d’intrusion. L’outil que j’ai développé suit toute cette démarche pour déterminer la liste des utilisateurs et la politique de mot de passe effective pour chacun d’entre eux. Si l’outil n’est pas capable de lire le contenu des PSO, il se contentera d’ignorer les comptes affectés lors des tests.

Mais j’ai voulu aller un peu plus loin. On a vu qu’au bout d’une certaine durée, l’attribut badPwdCount des utilisateurs était réinitialisé. Cette certaine durée, qu’on retrouve dans l’attribut lockoutObservationWindow sur le domaine, ou dans l’attribut msDS-LockoutObservationWindow des PSO, peut ainsi varier d’un utilisateur à l’autre.

L’outil que j’ai développé prend en entrée une liste de mots de passe qu’on souhaite tester sur les utilisateurs, et il va tenter tous les mots de passe sur tous les utilisateurs, en prenant soin de respecter les seuils de verrouillages, les temps d’attente pour que le compteur soit remis à zéro pour pouvoir continuer les tests.

Pour que tout ça fonctionne sans accroc, l’outil commence par récupérer l’heure du contrôleur de domaine pour être parfaitement synchronisé, et se synchronise régulièrement avec le LDAP (on n’est pas à l’abri d’un vrai utilisateur qui se trompe de mot de passe pendant notre password spraying).

Bref, je suis super heureux de partager avec vous l’outil conpass, qui m’est extrêmement utile en tests d’intrusion, j’espère qu’il le sera autant pour vous.

Outil conpass en action

Outil conpass en action

Alors attention, il a fonctionné durant mes derniers pentests, mais ça reste un outil qui va tester des mots de passe, écrit par un humain qui fait des erreurs, donc il est possible qu’il y ait des bugs et que ça plante, ou que ça verrouille des comptes. Je suis donc très preneur de retours, de tests dans des environnements maitrisés, pour qu’il soit le plus robuste possible.

Ceci est un cross-post de la version anglaise : https://en.hackndo.com/password-spraying-lockout/

Romain Bentz (pixis)Leader Audit
Passionné de sécurité informatique, avec un attrait particulier pour la sécurité des réseaux d’entreprises sous Active Directory 🍄

Add a comment

*Please complete all fields correctly