Attaque sur la base de données du contrôleur de domaine (NTDS.DIT)

[post-views]
mai 10, 2016 · 9 min de lecture
Attaque sur la base de données du contrôleur de domaine (NTDS.DIT)

Donc, comme je l’ai promis, nous commençons le processus d’analyse des différentes étapes du Cyber Kill Chain de l’attaque précédemment décrite. Aujourd’hui, nous examinerons un des vecteurs d’attaque sur l’infrastructure de l’entreprise, que nous pouvons compter comme deux étapes : «Actions sur les Objectifs» et «Reconnaissance». Nos objectifs sont :

  • Prendre pied en utilisant les comptes obtenus ;
  • Obtenir un maximum d’informations sur l’entreprise (email, noms de départements, numéros de téléphone, titres fonctionnels, etc.) pour des attaques futures ou même vendre l’accès à son infrastructure.

SYSTEM et NTDS.DIT

Les adversaires, une fois dans le réseau d’entreprise, s’attaquent à un des morceaux les «plus savoureux» des informations d’ActiveDirectory, qui sont les fichiers SYSTEM et NTDS.DIT. Ces fichiers sont des bases de données, qui contiennent toutes les données d’ActiveDirectory. NTDS.DIT contient des informations sur tous les utilisateurs du domaine, y compris les hash des mots de passe. Le fichier SYSTEM est nécessaire pour déchiffrer les données de NTDS.DIT.

Je ne décrirai pas les méthodes de récupération de hash dans cet article, car de nombreux articles sur ce sujet ont déjà été écrits. Je me concentrerai sur la méthode qui montre la vulnérabilité de l’infrastructure par l’exposition des mots de passe (si des hash LM sont disponibles), et l’automatisation du processus de recherche qui le rend extrêmement rapide.

Nous avons donc besoin uniquement des hash LM et NTLM :ntds_dit_2Après avoir reçu les hash, nous commençons par le hash LM.

À propos du hash LM

Quelques informations sur le hash LM.

Il est basé sur le DES chiffrement par bloc et peut être facilement attaqué pour un craquage de mot de passe en raison de deux vulnérabilités dans sa réalisation. Premièrement, les mots de passe de plus de 7 caractères sont divisés en deux parties et chaque partie est hashée séparément, ce qui permet d’attaquer chaque partie séparément. Deuxièmement, tous les caractères minuscules sont convertis en majuscules.

Donc, nous avons :

Le hash LM qui, comme nous l’avons compris précédemment, a deux parties.9196B21FEF3C8906AAD3B435B51404EE

AAD3B435B51404EE – ce hash provient d’un mot de passe vide (cette séquence de chiffres signifie qu’une moitié du hash est un mot de passe vide).

Nous concluons donc que le mot de passe comporte moins de sept caractères, car la deuxième partie du hash correspond à un ensemble de caractères vide.

Maintenant, pour casser la première partie

À cet effet, nous utilisons hashcat, qui permet un craquage GPU parallèle puissant. En utilisant les clés suivantes :

-a => mode d’attaque

-m => type de hash

?d = tous les chiffres (0–9).

?l = caractères minuscules (a–z).

?u = caractères majuscules (A–Z).

?s = symboles.

ntds_dit_3Nous recevons le mot de passe en 24 secondes.ntds_dit_4Maintenant c’est au tour du NTLM1BC10704ED604747D7D827FC7A43D555Il est beaucoup plus facile de le casser en force brute, car nous connaissons les informations suivantes :

  1. Quels caractères sont utilisés dans le mot de passe ;
  2. Ordre de ces caractères.

Nous n’avons qu’à vérifier si un caractère est en majuscule ou en minuscule.ntds_dit_5

ntds_dit_6Ainsi, parce que nous avons un hash LM, tout le travail nous a pris un peu plus de 32 secondes.

Nous allons encore compliquer la tâche :

Supposons que nous ayons un mot de passe de 14 caractères avec le troisième niveau de difficulté (mot de passe classique d’entreprise) :29355BC0D45C341B51ACD8D3923F7C21Nous utilisons le même stratagème :ntds_dit_7La force brute nous a donné la première approximation (mot de passe en caractères majuscules) en 31 secondes.29355BC0D45C341B51ACD8D3923F7C21

ntds_dit_8Maintenant, tout ce que nous devons faire est

NTLM :E06E777CD11F495E9B9098B5576A4343

ntds_dit_9

L’augmentation de la complexité du mot de passe même jusqu’à 14 caractères ne rend pas notre tâche plus difficile – si nous avons un hash LM, le craquage ne prend que 40 secondes !Nous avons traité un hash. Si nous devions traiter une grande quantité de hash, construire des masques pour chaque mot de passe serait trop laborieux. C’est pourquoi j’ai développé un outil qui ferait le travail suivant pour nous – ntlm_mask_gen.exe (vous pouvez le télécharger ici tut, MD5: c2a9dac79c51e14c84f35febd72d05ba ou prendre le code python dans Annexe 1) :

  1. Il forme des listes de mots pour chaque mot de passe unique ;
  2. Il forme un masque pour chaque mot de passe unique inclus dans les listes de mots formées ;
  3. Il forme un seul fichier avec des chaînes pour chaque hash, masque et liste de mots séparés.

Tout ce que vous avez à faire ensuite est d’exécuter ce fichier et de regarder hashcat craquer des mots de passe en quelques secondes.

Démonstration de la méthodologie décrite

Effectuons une autre expérience pour démontrer la technique décrite :

Nous utiliserons 10 mots de passe avec 10 caractères, quatrième niveau de difficulté avec les paramètres suivants (exigences traditionnelles pour un compte technologique/administratif/système selon la politique de mot de passe d’entreprise) :ntds_dit_10

  1. Nous créons un fichier avec les hash csv:
    ntds_dit_11
  1. Ensuite, nous créons un fichier pour casser cmd :ntds_dit_12
  1. Et maintenant nous recevons les résultats (divisés en deux parties) :ntds_dit_13
  1. Ensuite, nous faisons correspondre les mots de passe des deux moitiés en utilisant la clé –show :ntds_dit_14
    test_lm_full.result :ntds_dit_15
  1. Ensuite, nous créons un fichier pour notre outil, qui générera des listes de mots et des masques pour nous. Nous prenons le hash NTLM et le mot de passe pour casser LM, par exemple test_ntlm_input.txt:
    ntds_dit_16
  1. Exécuter notre outil :ntds_dit_17
    Immédiatement, nous recevons un fichier prêt pour la recherche de mot de passe par masques et listes de mots formés automatiquement :

    ntds_dit_18

  1. Nous exécutons ce fichier et obtenons nos mots de passe en 14 secondes :ntds_dit_19

ntds_dit_20C’est tout.

Clarification

Comme vous le savez, à partir de la version 2008, le stockage des hash LM est désactivé par défaut, mais en cas de migration de la version 2003 (ou inférieure), les comptes qui n’ont pas modifié leurs mots de passe après migration restent avec un hash LM dans la base de données. Généralement, ce sont des comptes technologiques avec des mots de passe qui ne sont pas changés pour plusieurs raisons, par exemple, ils peuvent provoquer un plantage de certains services critiques, etc. De tels comptes sont une menace sérieuse car leurs mots de passe sont souvent « Ne jamais expirer », leur accès n’est pas surveillé et ils ont fréquemment des privilèges élevés jusqu’à l’accès administratif. En conséquence, utiliser de tels comptes pour une intrusion sera la plus discrète.

Conclusion

Il est fondamental de renoncer aux domaines basés sur 2003 ou antérieurs et d’utiliser des versions plus récentes. En cas de migration, vous devez vous assurer que tous les comptes ont modifié leurs mots de passe et qu’il n’y a pas de hash LM dans la base de données. Et un autre conseil pour les administrateurs de domaine et les experts en sécurité de l’information, vous devriez travailler de manière proactive et craquer vos mots de passe au moins une fois par trimestre ! Vous devez contrôler l’accès à AD en particulier en surveillant les opérations avec les fichiers SYSTEM et NTDS.DIT.

J’espère que cet article sera utile pour les experts en sécurité de l’information, qui peuvent utiliser les techniques décrites comme arguments lors de discussions avec les spécialistes en informatique. Ou il sera utile pour les administrateurs dans le but d’une meilleure compréhension des risques liés aux attaques sur ActiveDirectory.

Annexe 1

import math

alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'exception = ' &%{}<>^|"'file_name = open('D:hashcatkd_input.new','r')main_len = len(file_name.readlines())file_name.close()file_name = open('D:hashcatkd_input.new','r')file_name_out = open('D:hashcatkd_input.cmd','w')hashes = []passwords = []masks = [[] for i in range(main_len)]dicts = []char_sets_count = 0char_sets = [[] for i in range(main_len)]ind_main = 0
ch1 = []
ch2 = []
ch3 = []
ch4 = []ch_sets = [ch1, ch2, ch3, ch4]


def new_init(pass_letter):
    for ind_0 in range(4):ch_sets[ind_0] = []
    return predict(pass_letter)


def predict(new_password):pass_letter = ''
    for let in new_password:
        if let in alphabet and not (let in pass_letter):pass_letter += let
    return dict_generator(pass_letter)


def dict_generator(pass_letter):
    global char_sets_count

    dict_new = ''pass_len = len(pass_letter)
    if pass_len < 4:
        for ind1 in range(pass_len):ch_sets[ind1].append(pass_letter[ind1])ch_sets[ind1].append(pass_letter[ind1].lower())
    else:filler(pass_letter, spreader(pass_len))
    for ind2 in range(4):
        if len(ch_sets[ind2]) > 0:dict_new += '-' + str(ind2+1) + ' ' + ''.join(ch_sets[ind2]) + ' 'char_sets[char_sets_count] = [ch_sets[0], ch_sets[1], ch_sets[2], ch_sets[3]]char_sets_count += 1
    return dict_newdef spreader(letter_num):spread_counter = [0, 0, 0, 0]
    for ind3 in range(4):spread_counter[ind3] = int(math.ceil(letter_num/float(4-ind3)))letter_num -= spread_counter[ind3]
    return spread_counterdef filler(pass_letter, counter_letter):count_l = 0
    for ind_ch in range(4):
        for ind_set in range(counter_letter[ind_ch]):ch_sets[ind_ch].append(pass_letter[count_l])ch_sets[ind_ch].append(pass_letter[count_l].lower())count_l += 1


def mask_generator(password,pwd_idx):mask_new = ''
    for pw_let in password:
        if pw_let in alphabet:
            for ind_array in range(4):
                if pw_let in char_sets[pwd_idx][ind_array]:mask_new += '?'+str(ind_array+1)
        elif pw_let in exception:mask_new += '?s'
        else:mask_new += pw_let

    masks[pwd_idx] = mask_new# ---------------------- Main --------------------------------

for line in file_name:hashes.append(line[:32])passwords.append(line[33:len(line)-1])dicts.append(new_init(passwords[ind_main]))ind_main += 1

for pwd_idx in range(len(passwords)):mask_generator(passwords[pwd_idx],pwd_idx)


for index in range(len(hashes)):text = 'cudaHashcat64.exe -m 1000 -a 3 -o ntlm_tesult.hash ' + str(hashes[index]) + ' ' + str(dicts[index]) + ' ' + str(masks[index]) + 'n'file_name_out.write(text)file_name.close()file_name_out.close()

Table des Matières

Cet article vous a-t-il été utile ?

Aimez-le et partagez-le avec vos collègues.
Rejoignez la plateforme Detection as Code de SOC Prime pour améliorer la visibilité des menaces les plus pertinentes pour votre entreprise. Pour vous aider à démarrer et générer une valeur immédiate, réservez dès maintenant une réunion avec les experts de SOC Prime.