Attacco al database del domain controller (NTDS.DIT)

[post-views]
Maggio 10, 2016 · 8 min di lettura
Attacco al database del domain controller (NTDS.DIT)

Quindi, come ho promesso, iniziamo il processo di analisi delle singole fasi della Cyber Kill Chain dell’attacco descritto in precedenza. Oggi esamineremo uno dei vettori di attacco sull’infrastruttura aziendale, che possiamo considerare come due fasi: «Azioni sugli Obiettivi» e «Ricognizione». I nostri obiettivi sono:

  • Ottenere una base stabile utilizzando gli account ottenuti;
  • Ottenere il massimo delle informazioni sull’Azienda (email, nomi dei dipartimenti, numeri di telefono, titoli funzionali ecc.) per ulteriori attacchi o persino vendere accesso alla sua infrastruttura.

SYSTEM e NTDS.DIT

Gli avversari, una volta entrati nella rete aziendale, mireranno a uno dei “pezzi più golosi” delle informazioni di ActiveDirectory, che sono i file SYSTEM e NTDS.DIT. Questi file sono database, che contengono tutti i dati di ActiveDirectory. NTDS.DIT contiene informazioni su tutti gli utenti nel dominio, inclusi gli hash delle password. Il file SYSTEM è necessario per decriptare i dati da NTDS.DIT.

Non descriverò i metodi di recupero degli hash in questo articolo, perché sono già stati scritti molti articoli su quel soggetto. Mi concentrerò sul metodo che mostra la vulnerabilità dell’infrastruttura tramite l’esposizione delle password (se sono disponibili gli hash LM) e sull’automazione del processo di ricerca che lo rende estremamente veloce.

Quindi, abbiamo bisogno solo degli hash LM e NTLM:ntds_dit_2Dopo aver ricevuto gli hash, iniziamo con l’hash LM.

A proposito dell’hash LM

Alcune informazioni sull’hash LM.

È basato su un DES cifrario a blocchi e può essere facilmente attaccato per il cracking delle password a causa di due vulnerabilità nella sua realizzazione. In primo luogo, le password più lunghe di 7 caratteri sono divise in due parti e ciascuna parte è hashata separatamente, permettendo di attaccare ciascuna parte separatamente. In secondo luogo, tutti i caratteri minuscoli sono convertiti in maiuscoli.

Quindi, abbiamo:

L’hash LM, che, come abbiamo capito prima, ha due parti.9196B21FEF3C8906AAD3B435B51404EE

AAD3B435B51404EE– questo hash è da una password vuota (tale sequenza di numerali significa che una metà dell’hash è una password vuota).

Concludiamo che la password è composta da meno di sette caratteri, perché la seconda parte dell’hash corrisponde con un set di caratteri vuoto.

Ora per fare brute-forcing della prima parte

A questo scopo usiamohashcat, che permette un forte brute-forcing GPU parallelizzato. Usando i seguenti chiavi:

-a => modalità di attacco

-m => tipo di hash

?d = tutti i decimali (0–9).

?l = caratteri minuscoli (a–z).

?u = caratteri maiuscoli (A–Z).

?s = simboli.

ntds_dit_3Riceviamo la password in 24 secondi.ntds_dit_4Ora è il turno del NTLM1BC10704ED604747D7D827FC7A43D555È molto più facile fare brute-force perché conosciamo le seguenti informazioni:

  1. Quali caratteri sono usati nella password;
  2. Ordine di questi caratteri.

Dobbiamo solo verificare se un carattere è maiuscolo o minuscolo.ntds_dit_5

ntds_dit_6Così, poiché abbiamo un hash LM tutto il lavoro ci ha preso poco più di 32 secondi.

Complicheremo ulteriormente il compito:

Supponiamo di avere una password di 14 caratteri con il terzo livello di difficoltà (password corporativa classica):29355BC0D45C341B51ACD8D3923F7C21Usiamo lo stesso trucco:ntds_dit_7Il brute-force ci ha dato la prima approssimazione (password in caratteri maiuscoli) in 31 secondi.29355BC0D45C341B51ACD8D3923F7C21

ntds_dit_8Ora tutto ciò che dobbiamo fare è

NTLM:E06E777CD11F495E9B9098B5576A4343

ntds_dit_9

Aumentare la complessità della password fino a 14 caratteri non rende il nostro compito più difficile – se abbiamo l’hash LM, il cracking richiede solo 40 secondi!Abbiamo elaborato un hash. Se avessimo bisogno di elaborare una grande quantità di hash, costruire maschere per ogni password sarebbe troppo laborioso. Ecco perché ho sviluppato uno strumento che farà il seguente lavoro per noi – ntlm_mask_gen.exe (puoi scaricarlo qui qui, MD5: c2a9dac79c51e14c84f35febd72d05bao prendi il codice python in Allegato 1) :

  1. Forma wordlists per ogni singola password;
  2. Forma maschere per ogni singola password, incluso delle wordlists formate;
  3. Forma un file unico con stringhe per ogni singolo hash, maschera e wordlist.

Tutto ciò che devi fare allora è eseguire questo file e guardare hashcat i cracking delle password in pochi secondi.

Dimostrazione della metodologia descritta

Facciamo un altro esperimento per dimostrare la tecnica descritta:

Useremo 10 password con 10 caratteri, quarto livello di difficoltà con le seguenti impostazioni (requisiti tradizionali per account tecnologico/amministrativo/sistemico dalla politica di password aziendale):ntds_dit_10

  1. Creiamo un file con gli hashcsv:
    ntds_dit_11
  1. Quindi creiamo un file per il cracking cmd:ntds_dit_12
  1. E ora riceviamo i risultati (divisi in due parti):ntds_dit_13
  1. Poi abbiniamo le password delle due metà usando il tasto –show:ntds_dit_14
    test_lm_full.result:ntds_dit_15
  1. Quindi creiamo un file per il nostro strumento, che genererà wordlists e maschere per noi. Prendiamo l’hash NTLM e la password per il cracking LM, ad esempiotest_ntlm_input.txt:
    ntds_dit_16
  1. Esegui il nostro strumento:ntds_dit_17
    Immediatamente riceviamo un file che è pronto per la ricerca delle password tramite maschere e wordlists formate automaticamente:

    ntds_dit_18

  1. Eseguiamo questo file e otteniamo le nostre password in 14 secondi:ntds_dit_19

ntds_dit_20Questo è tutto.

Chiarimento

Come sapete, a partire dalla versione 2008, l’archiviazione degli hash LM è disabilitata di default, ma in caso di migrazione dalla versione 2003 (o inferiore), gli account che non hanno cambiato password dopo la migrazione, rimangono con l’hash LM nel database. Di solito questi sono account tecnologici con password che non vengono cambiate per diversi motivi, ad esempio, potrebbero causare il crash di alcuni servizi critici, ecc. Tali account rappresentano una minaccia seria perché le loro password spesso non «Scadono Mai», il loro accesso non è monitorato e frequentemente hanno alti privilegi fino all’accesso amministrativo. Di conseguenza, usare tali account per entrare sarà il più discreto possibile.

Conclusione

È di fondamentale importanza rinunciare ai domini basati su 2003 o versioni inferiori e utilizzare versioni più recenti. In caso di migrazione, devi assicurarti che tutti gli account abbiano cambiato la loro password e che non ci siano hash LM nel database. E un altro consiglio per gli amministratori di dominio e gli esperti di sicurezza informatica, dovreste lavorare proattivamente e fare brute-force delle vostre password almeno una volta al trimestre! Dovreste controllare l’accesso a AD specialmente monitorando le operazioni con i file SYSTEM e NTDS.DIT.

Spero che questo articolo sia utile per gli esperti di sicurezza informatica, che possono usare le tecniche descritte come argomenti durante la comunicazione con gli specialisti IT. O sarà utile per gli amministratori al fine di comprendere più ampiamente i rischi legati agli attacchi su ActiveDirectory.

Allegato 1

import math

alfabeto = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'eccezione = ' &%{}<>^|"'nome_file = aprire('D:hashcatkd_input.new','r')len_principale = len(nome_file.leggi_linee())nome_file.chiudere()nome_file = aprire('D:hashcatkd_input.new','r')nome_file_out = aprire('D:hashcatkd_input.cmd','w')hashes = []password = []maschere = [[] for i in gamma(len_principale)]dizionari = []conteggio_set_caratteri = 0set_caratteri = [[] for i in gamma(len_principale)]ind_principale = 0
ch1 = []
ch2 = []
ch3 = []
ch4 = []set_ch = [ch1, ch2, ch3, ch4]


def nuovo_init(lettera_pass):
    for ind_0 in gamma(4):set_ch[ind_0] = []
    ritorno prevedere(lettera_pass)


def prevedere(nuova_password):lettera_pass = ''
    for let in nuova_password:
        if let in alfabeto and not (let in lettera_pass):lettera_pass += let
    ritorno generatore_diz(lettera_pass)


def generatore_diz(lettera_pass):
    globale conteggio_set_caratteri

    diz_nuovo = ''len_pass = len(lettera_pass)
    if len_pass < 4:
        for ind1 in gamma(len_pass):set_ch[ind1].aggiungi(lettera_pass[ind1])set_ch[ind1].aggiungi(lettera_pass[ind1].minuscolo())
    altrimenti:riempitivo(lettera_pass, diffusore(len_pass))
    for ind2 in gamma(4):
        if len(set_ch[ind2]) > 0:diz_nuovo += '-' + str(ind2+1) + ' ' + ''.unisci(set_ch[ind2]) + ' 'set_caratteri[conteggio_set_caratteri] = [set_ch[0], set_ch[1], set_ch[2], set_ch[3]]conteggio_set_caratteri += 1
    ritorno diz_nuovodef diffusore(numero_lettera):contatore_diffusione = [0, 0, 0, 0]
    for ind3 in gamma(4):contatore_diffusione[ind3] = int(matematica.arrotondamento(numero_lettera/flottante(4-ind3)))numero_lettera -= contatore_diffusione[ind3]
    ritorno contatore_diffusionedef riempitivo(lettera_pass, contatore_lettera):conta_l = 0
    for ind_ch in gamma(4):
        for ind_set in gamma(contatore_lettera[ind_ch]):set_ch[ind_ch].aggiungi(lettera_pass[conta_l])set_ch[ind_ch].aggiungi(lettera_pass[conta_l].minuscolo())conta_l += 1


def generatore_maschera(password,pwd_idx):nuova_maschera = ''
    for pw_let in password:
        if pw_let in alfabeto:
            for ind_array in gamma(4):
                if pw_let in set_caratteri[pwd_idx][ind_array]:nuova_maschera += '?'+str(ind_array+1)
        altrimenti se pw_let in eccezione:nuova_maschera += '?s'
        altrimenti:nuova_maschera += pw_let

    maschere[pwd_idx] = nuova_maschera# ---------------------- Principale --------------------------------

for linea in nome_file:hashes.aggiungi(linea[:32])password.aggiungi(linea[33:len(linea)-1])dizionari.aggiungi(nuovo_init(password[ind_principale]))ind_principale += 1

for pwd_idx in gamma(len(password)):generatore_maschera(password[pwd_idx],pwd_idx)


for indice in gamma(len(hashes)):testo = 'cudaHashcat64.exe -m 1000 -a 3 -o ntlm_tesult.hash ' + str(hashes[indice]) + ' ' + str(dizionari[indice]) + ' ' + str(maschere[indice]) + 'n'nome_file_out.scrivi(testo)nome_file.chiudere()nome_file_out.chiudere()

Indice dei Contenuti

Questo articolo è stato utile?

Metti mi piace e condividilo con i tuoi colleghi.
Unisciti alla piattaforma Detection as Code di SOC Prime per migliorare la visibilità sulle minacce più rilevanti per il tuo business. Per aiutarti a iniziare e ottenere valore immediato, prenota ora un incontro con gli esperti di SOC Prime.