Hackez vos mots de passe avant que ce soit un pirate qui le fasse
Dans votre domaine Windows, il y a des utilisateurs.
Parmi ces utilisateurs, il y a Fred qui vient de Toulouse et dont le mot de passe est "Toulouse31!" (on ne peut pas lui reprocher de ne pas respecter les critères de complexité : minuscules, majuscules, chiffres, ponctuation) ;
Il y a ext_technisave, le compte de votre infogérant, dont le mot de passe est TechniS@ve2018 ;
Il y a print_cantine, un compte de service qui existe depuis bien avant votre entrée dans la boite, dont le mot de passe est "cantine".
Peut être que vous vous êtes reconnus dans cette description ou peut être que vous avez pensé « Diable que sais-je des mots de passe de mes utilisateurs moi ? ».
En tant qu'admin système ou RSSI, vous savez ce que vous demandez à vos utilisateurs (mot de passe long, avec des majuscules, chiffres, ponctuation, etc.) mais vous ne savez pas comment ils le respectent. Cet angle mort de la sécurité est une vraie source de faiblesse, partagée par de nombreuses entreprises (on pourrait dire "toutes" sans faire une grosse erreur).
Si vous possédez un service avec authentification exposé sur Internet (Email, VPN, SSH, etc.) et que l'utilisateur test a le mot de passe test, vous risquez de vous retrouver avec du monde chez vous.
Un pirate pourrait aussi avoir obtenu un accès initial dans votre réseau (pièce jointe malveillante, F5 BigIP non à jour, etc.) et vouloir trouver le mot de passe Administrateur du domaine pour pouvoir aller faire le zouave sur tous les postes et serveurs. Donc si le mot de passe de cet Administrateur est bonjour, le réseau ne va pas passer des moments Nutella.
Mais il n'y a pas que l'Administrateur du domaine qui est concerné. Vous avez souvent d'autres comptes qui ont des droits d'administration : le compte de l'antivirus, le compte de l'outil de sauvegarde, etc. Il suffit qu'un seul d'entre eux ait un mot de passe trop prédictible (hum hum veeam:veeam) et c'est le drame.
Et, finalement, même les comptes qui n'ont pas de droits d'administration peuvent faire des choses intéressantes : accéder à des fichiers sensibles sur les partages ou même remplacer des fichiers par des malwares pour piéger d'autres utilisateurs, accéder à des outils internes (paye, dépot de code, ERP) et effacer/modifier leur contenu, ouvrir des sessions distantes sur d'autres machines pour y déposer des malware, etc.
Lors des audits de sécurité internes, c'est souvent la découverte d'un seul compte avec un mot de passe faible (le légendaire stagiaire:stagiaire) qui permet d'attraper un fil rouge dont le bout est la compromission de tout le réseau. Et inversement, il est très rare de tomber sur un réseau où il n'y a AUCUN mot de passe faible.
De ce fait, la plupart des audits internes se soldent par un élégant "RISQUE CRITIQUE" en première page.
Mais si les mots de passe des utilisateurs étaient régulièrement testés (et modifiés lorsqu'ils sont trop faibles), les intrusions se passeraient moins docilement pour les auditeurs et les pirates.
Nous recommandons, dans nos rapports d'audit, d'effectuer un test annuel de robustesse des mots de passe de l'AD.
Mais force est de constater que l'outillage à disposition des RSSI et Admins Systèmes, pour cette tâche, est famélique.
Qu'à ne cela tienne, nous en avons donc fait un !
On distingue deux types d'attaques contre les mots de passe.
Ce fameux indice, vous le savez peut être, est le résultat d'une fonction de hachage, appelé empreinte (ou hash en anglais). L'attaquant peut prendre plein de mots de passe possibles, les donner en entrée à cette fonction de hachage et si l'empreinte produite est identique à celle du bon mot de passe, c'est qu'il a trouvé le bon mot de passe.
Vous êtes peut être déjà familier des fonctions de hachage (MD5, SHA-1, SHA256, bcrypt, ...). Leur propriété fondamentale est d'être non-inversibles : si je vous donne une entrée, vous pouvez calculer son empreinte en quelques millisecondes, mais si je vous donne une empreinte, vous ne pouvez pas en déduire son entrée. L'empreinte 1817ac59c84467458e3f16fcbdd2ae28 ne laisse transparaître aucune indication sur ce qu'était son entrée. Mais c'est quand même un indice inestimable pour un pirate : pour chaque entrée qu'il soupçonne d'être la bonne, il peut en calculer l'empreinte en quelques millisecondes et voir si elle correspond à 1817ac59c84467458e3f16fcbdd2ae28.
C'est ainsi que fonctionnent les attaques hors ligne.
Active Directory ne stocke pas directement les mots de passe des utilisateurs, il en stocke les empreintes. Ainsi, si quelqu'un accède à sa base de données, les mots de passe des utilisateurs ne sont pas directement exposés (l'attaquant doit réussir une attaque hors ligne contre chacun d'eux).
Mais stocker les empreintes permet quand même à l'AD de vérifier l'authentification d'un utilisateur. En effet, si l'utilisateur marcel est associé à l'empreinte ed417b63f16b1e6265a4ef92e78bbab2 dans la base de l'AD et qu'un utilisateur prétend s'authentifier sur le compte de marcel avec le mot de passe "brouette", l'AD a simplement à calculer l'empreinte de "brouette" (quelques ms) et à vérifier si elle correspond bien à ed417b63f16b1e6265a4ef92e78bbab2.
Dans un environnement Active Directory, il y a malheureusement de nombreuses actions où l'empreinte d'un mot de passe est exposée : obtention d'un ticket kerberos, accès à un partage distant, mise en cache des comptes sur une machine, ... C'est pour cela qu'on recommande de tester la robustesse des mots de passe utilisateurs face à une attaque hors ligne. D'une part cela respect le principe de Kerckhoffs en traitant le pire des cas. D'autre part, en ayant évalué la robustesse face à une attaque hors ligne, on peut en déduire celle face à une attaque en ligne (l'inverse n'est pas possible).
Pour réaliser cet audit vous aurez besoin :
pip install ldapdomaindump impacket click
)La première étape est de récupérer la base des hash des mots de passe de vos utilisateurs.
Pour faire simple, la base des utilisateurs de l'AD c'est la base des comptes locaux des contrôleurs du domaine. Cette base des comptes locaux, sous n'importe quel système Windows, est matérialisée par 3 fichiers sous C:\Windows\System32\config\
:
Le hic est que leur accès est verrouillé pendant que le système est en fonctionnement.
Nous allons voir plusieurs alternatives pour les exporter.
Vos contrôleurs de domaine sont vraisemblablement sauvegardés (si ce n'est pas le cas vous êtes plutôt mal). Une solution simple est d'aller piocher ces 3 fichiers dans une sauvegarde via l'interface de votre outil. La plupart des grosses solutions commerciales (Veeam, ...) permettent d'explorer le système de fichiers des images de sauvegarde.
Par exemple, via la fonctionnalité qui permet de restaurer des fichiers spécifiques à l'endroit de votre choix. Vous pouvez ainsi restaurer la version la plus récente de ces 3 fichiers dans le répertoire personnel de votre utilisateur. Ces fichiers restaurés ne seront pas verrouillés par le système.
C'est la meilleure solution car elle ne risque pas d'être bloquée par votre EDR ou votre antivirus.
Une fois les 3 fichiers récupérés, il faut en extraire la base des hash. L'outil python secretsdump
de la suite impacket
va nous le permettre simplement :
secretsdump.py LOCAL -sam SAM -security SECURITY -system SYSTEM -outputfile hashes.txt
Volume Shadow Copy Service (VSS) est une fonctionnalité intégrée à Windows qui permet de restaurer votre système à un état antérieur.
L'utilitaire vssadmin
permet d'utiliser ce service en ligne de commande.
Vous pouvez créer une shadow copy du disque C puis la monter comme un disque :
vssadmin create shadow /for=C:
mklink /d c:\shadowcopy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy?\
Ensuite il ne vous reste qu'à vous rendre dans C:\shadowcopy\Windows\System32\config\
et à copier les 3 fichiers qui nous intéressent.
Le désavantage de cette solution est qu'elle fait souvent sonner les EDR/AV. Donc vous ne pourrez peut être pas l'utiliser.
Si vous avez réussi de cette manière, il faut également en extraire la bse des hash :
secretsdump.py LOCAL -sam SAM -security SECURITY -system SYSTEM -outputfile hashes.txt
Le fichier NTDS.dit contient toute la base de l'AD (notamment les utilisateurs). Il se trouve normalement sous C:\Windows\ntds\ntds.dit
. Mais son accès est également protégé.
Il existe une commande permettant de réaliser un export de ce fichier :
ntdsutil "ac i ntds" "ifm" "create full c:\copy-ntds" quit quit
Vous n'avez qu'à vous rendre dans le répertoire C:\copy-ntds et à récupérer les fichiers NTDS.dit
et SYSTEM
qui s'y trouvent.
Utilisez l'outil secretsdump
pour extraire la base des hash de ces deux fichiers :
secretsdump.py LOCAL -ntds NTDS.dit -system SYSTEM -outputfile hashes.txt
Ici aussi l'opération peut être bloquée par un EDR/AV.
L'outil secretsdump
peut aussi être utilisé à distance (avec un compte admin du domaine) pour effectuer automatiquement les opérations de récupération :
secretsdump.py <DOMAIN>/<USER>@<DC_IP> p <PASSWORD> -outputfile hashes.txt
Ici aussi l'opération peut être bloquée par un EDR/AV.
Vous allez peut être vous dire que si on a les fichiers SAM, SYSTEM et SECURITY on a déjà tout ce qu'il nous faut niveau base des utilisateurs. Pas tout à fait. Ce qui va nous intéresser ce sont aussi les attributs de ces comptes dans Active Directory : est-ce qu'il sont désactivés, à quels groupes ils appartiennent, ...
Pour cela, il existe un outil qui produit un résultat très facilement exploitable : ldapdomaindump
. C'est un outil python, qui peut donc être utilisé aussi bien sur Linux que sur Windows. Il s'utilise à l'aide d'un compte du domaine :
ldapdomaindump -u <DOMAIN>\\<USER> -p <PASSWORD> --no-html --no-json ldap://<DC_IP>:389
Il produira plusieurs fichiers décrivant la base Active Directory. Celui qui nous intéresse est domain_users.grep
.
Bien, maintenant nous avons tout le nécessaire pour se lancer dans l'audit de la robustesse de ces hash.
Nous nous concentrerons sur les hash au format NTLM (abrégé NT). Mais il peut être pertinent de vérifier que vous n'avez pas des hash dans l'ancien format LM (LanMan), auquel cas tous les mots de passe de vos utilisateurs sont à risque, même ceux qui ont été choisis de manière sécurisée.
Pour le vérifier, vous pouvez ouvrir le fichier hashes.txt et regarder les lignes qui ont la forme :
nom d'utilisateur (éventuellement précédé du nom du domaine) : un numéro d'utilisateur : une suite de 32 caractères hexadécimaux : une autre suite de 32 caractères hexadécimaux :::
.
Par exemple :
mydomain\myuser:1530:aad3b435b51404eeaad3b435b51404ee:ad38316b9d8a9f6dd210d806d5877bcf:::
La première suite de 32 caractères hexadécimaux correspond aux hash LM et la seconde aux hash NT. La première doit toujours valoir aad3b435b51404eeaad3b435b51404ee
qui correspond à un mot de passe vide. Si vous repérez une exception, ça signifie que le mot de passe est aussi stocké en version LanMan (ce qui est une vulnérabilité). Pour corriger le problème, suivez cette procédure.
Il y a un moyen assez simple d'avoir une bonne idée de la robustesse générale des mots de passe, c'est de comparer les hash avec la base du site HIBP.
L'outil LennieTheLeaker.py
de la suite Lestat va nous y aider. Pour chaque hash de notre base il va requêter l'API de HIPB et vérifier si le hash en question est compromis ou non.
L'avantage est que c'est très rapide (le plus long c'est de télécharger la base).
Le désavantage c'est que ça ne nous révélera pas les mots de passe : on saura seulement que le hash de tel utilisateur correspond à un mot de passe compromis, sans connaître ce mot de passe. Donc on ne pourra pas faire d'éducation ciblée en identifiant les motifs faibles que nos employés utilisent lorsqu'ils créent leur mot de passe.
Mais ça permet de répondre assez vite à la question : quelle proportion de mes comptes utilisateurs est exposée au password stuffing ?
La commande a exécuter est la suivante :
python LennieTheLeaker.py hashes.txt -w RESULT.txt
On peut s'inquiéter du fait de devoir communiquer nos hash au site HIPB. Après tout, je veux connaître mes mots de passe vulnérables mais je ne veux pas qu'un tiers (le site HIPB) les connaisse aussi.
Ils ont bien conçu leur API pour minimiser ce problème. En fait on ne va pas interroger l'API en lui demandant directement "est-ce que le hash a523a8c091767efbd9e83f72c389e7e5 est compromis ?", auquel cas on lui révèlerait toute notre base de hash. On va lui demander : "donne moi tous les hash compromis que tu connais qui commencent par a523a" et on va vérifier si le hash a523a8c091767efbd9e83e72c389e7e5 est présent dans la réponse. Donc HIPB sait que l'un de nos utilisateurs possède un hash qui commence par a523a mais il ingore la suite. Or comme il reste 27 caractères hexadécimaux à deviner, il lui faudrait en moyenne 162 000 000 000 000 000 000 000 000 000 000 essais pour trouver le bon. Et inversement, le fait d'avoir précisé les 5 premiers caractères nous évite de chercher dans toute la base de HIPB pour chaque requête, ce qui serait trop volumineux.
Néanmoins si vous ne voulez exposer aucune information, l'outil fournit un moyen de télécharger la base en local (attention c'est très long) :
python LennieTheLeaker.py hashes.txt -db HIPB.txt -w RESULT.txt
[*] Parsing hashes file ...
[+] Parsing completed. 381 users detected with 331 unique NTLM hashes
[*] Checking local HaveIBeenPwned database for leaked passwords ...
[!] "HIPB.txt" file does not exist. Would you like to download the HIBP database ? It takes a long time
[y/n] : y
[*] Downloading HIPB database ...
[------------------------------------] 0% 1d 08:04:31
Une autre façon de faire (ou bien une façon complémentaire) est de simplement utiliser un outil de force brute pour tester tous les mots de passe possible (depuis le mot de passe "a" jusqu'au mot de passe "zzzzzzzzzzzzzzzzzzz").
Pour cela, vous pouvez utiliser l'outil john-the-ripper
:
john --format=nt --fork=<nombre de CPU> hashes.txt
Je vous conseille de vous équiper d'une machine avec un minimum de puissance quand même (pour un octocore, mettez donc --fork=8).
L'idée est de laisser tourner l'outil pendant le plus de temps possible (3 jours par exemple). Quand vous estimez que l'effort est représentatif de ce que pourrait y passer un adversaire, vous coupez l'outil (CTRL+C) et vous générez un fichier de résultat :
john --format=nt --show hashes.txt > RESULT.txt
Vous pouvez utiliser un autre outil de craquage de mot de passe bien sûr (comme hashcat) tant qu'à la fin vous pouvez exporter son résultat dans un format où chaque ligne est de la forme user:password
.
Les vrais pirates ne s'embêtent plus vraiment à faire de la force brute. Ils utilisent des dictionnaires (wordlist) de mots de passe probables :
Vous pouvez utiliser l'outil MikeTheMangler de la suite Lestat pour générer des wordlist qui dérivent le nom de la société ou des utilisateurs.
Par exemple, si vous êtes l'entreprise Airbus, vous pouvez générer des mots de passe probables basés sur des mots clés en les séparant par des virgules :
python MikeTheMangler.py --comb 1 Airbus,avion,A380
avion
Airbusavion
A380Airbus
A380
avionA380
A380avion
AirbusA380
avionAirbus
Airbus
Et vous pouvez y ajouter tout un tas de variations (majuscules, leet, ponctuation, nombres, ...) :
python MikeTheMangler.py --nick 0 --case 1 --leet 1 --num 1 --punc 1 --pref 0 --comb 1 Airbus,avion,A380
4irbus4vion2!
av1onA1rbus_0
a380airbus2
4vion01
Airbusavi0n_01
Airbu$_7
AirbusA380_0
a3802!
airbusavi0n2!
airbusa3802!
avi0nAirbus5
av!on1
airbusa3807
avionAirbu501!
A!rbus_7
avionairbus
avi0n7!
av1onA1rbus01!
...
N'hésitez pas à explorer les options avec python MikeTheMangler.py --help
. Et notamment à utiliser les listes de prénoms et de lieux que nous avons construites.
Chaque fois que vous avez généré une liste, vous pouvez utiliser john-the-ripper pour voir si elle permet de craquer de nouveaux hash :
john --format=nt --wordlist=<MALISTE> hashes.txt
Et à la fin vous exportez la liste de tous les hash craqués, d'un seul coup :
john --format=nt --show hashes.txt > RESULT.txt
Nous disposons maintenant d'un fichier RESULT.txt
qui contient les mots de passe craqués et du fichier domain_users.grep
.
C'est là que Lestat va enfin vous automatiser sérieusement les choses. Vous pouvez générer toute l'analyse avec la simple commande suivante :
python LesterTheLooter.py RESULT.txt domain_users.grep
Cela produit un fichier excel Lestat.xlsx avec 3 feuillets :
Il est également possible d'exporter en CSV ou juste sur la sortie standard.
Le premier feuillet du fichier excel liste les comptes craqués :
Pour chaque compte craqué, il est stipulé :
PS : pour anticiper votre question, oui je me suis assuré que le blur était résistant aux outils d'IA permettant de déflouter
Le deuxième feuillet liste les groupes compromis :
Pour chaque groupe il est stipulé :
Le dernier feuillet fournit des statistiques brutes (cachées dans l'images ci-dessous) et des graphiques permettant d'identifier les pratiques à risque dans l'entreprise.
Les statistiques portent sur deux groupes : celui de tous les comptes et celui des comptes activés seulement :
Les statistiques fournies comprennent :
Ces éléments peuvent vous aider à identifier des mauvaises pratiques répandues chez les utilisateurs et à mieux cibler les campagne de sensibilisation/éducation.
Retrouvez nos recommandations sur les bonnes pratiques concernant les mots de passe (probablement pas tout à fait celles que vous auriez pensées).
L'outil évolue régulièrement et gagnera en simplicité avec le temps. N'hésitez pas à nous faire part de vos retours dessus : contact@astar.org.