DEV Community

Cover image for LDAP protocol basics and the LDAP Injection attack
Grzegorz Piechnik
Grzegorz Piechnik

Posted on • Edited on

LDAP protocol basics and the LDAP Injection attack

It is very likely that when you go to your first job interview for a security position, you will encounter a question about the LDAP protocol. It is one of the basic concepts and is one of the most frequently discussed topics with people taking their first steps in the industry. In this article we will look at LDAP, learn about the LDAP Injection vulnerability and how to defend against it.

Lightweight Directory Access Protocol

Registered users on Linux systems are kept in the /etc/passwd file.

file: /etc/passwd
root:x:0:0:root:/root:/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
Enter fullscreen mode Exit fullscreen mode

When there are few supported machines and their users, managing them should not be much of a problem. On the other hand, when there is a high number of users, changing their passwords, deleting accounts, etc. can become problematic. Then centralized systems for managing user accounts come to the rescue. To implement them, LDAP protocol is most often used.

Lightweight Directory Access Protocol uses the TCP/IP protocol for information exchange. LDAP ultimately allows access to address directories, which can be compared to a standard relational database. OpenLDAP describes communication with the protocol as follows:

The LDAP directory service is based on a client-server model. One or more LDAP servers contain the data that makes up the directory information tree (DIT). A client connects to the servers and asks them a question. The server responds with an answer and/or an indication of where the client can obtain additional information (usually another LDAP server). Regardless of which LDAP server the client connects to, it sees the same view of the directory; the name presented to one LDAP server refers to the same entry that would be found on another LDAP server. This is an important feature of a global directory service such as LDAP.

https://www.openldap.org/doc/admin21/intro.html

LDAP is used in software such as Active Directory from Microsoft and SSSD on Linux systems, among others.

LDAP Injection

As with the SQL Injection attack, LDAP Injection involves the misuse of user input. Based on them, the application constructing LDAP statements, which are not filtered in any way, can lead to the execution of arbitrary commands on the server such as granting permissions to unauthorized queries and modifying the contents of the LDAP tree.

Examples

Access Controll Bypass

The first example we will discuss is used to bypass access control (Access Controll Bypass). Let's imagine a situation where there is a standard login page, where you have to enter a login and password to log in. To confirm the existence of a user in the application database, LDAP constructs search filters and sends them to the LDAP server, which processes only the first filter (USER). The sent construction looks as follows:

(&(USER=ENTERED_USERNAME_FROM_FORM)(PASSWORD=ENTERED_PASSWORD_FROM_FORM))
Enter fullscreen mode Exit fullscreen mode

Assuming that the user sends a valid username as the USER value with an additional string appended, our construction will look like this:

(&(USER=John)(&))(PASSWORD=ENTERED_PASSWORD_FROM_FORM))
Enter fullscreen mode Exit fullscreen mode

As you can see, the additional string that is included is )(&)). Thanks to it, it is possible to enclose the transmitted structure in a place we control. In addition, the LDAP server reads as a password the value &, which itself means absolute truth. This results in the server reading the request as correct, and we will be logged in. The rest of the construction, i.e. ((PASSWORD=ENTERED_PASSWORD_FROM_FORM)) is irrelevant.

Information Disclosure

Some LDAP systems use OR queries. Its form may look as follows:

(|(type=MY_TYPE_01)(type=MY_TYPE_02))
Enter fullscreen mode Exit fullscreen mode

The above constructs are used when we want to filter the database for several types of a given source. As an example, we could search for all blog posts whose category is programming or linux. Assuming that the server supports such filtering capability, we can set the value of category to linux)(uid=*)). Thus constructed, the structure looks as follows:

(|(category=linux)(uid=*))(category=programming))
Enter fullscreen mode Exit fullscreen mode

The asterisk sign on LDAP servers is interpreted as "all." This means that in the response we could (if the server was vulnerable) get all blog posts with the linux category and all users. This is because uid refers to the id of said users.

Blind LDAP Injection

The last of the ways to exploit vulnerable LDAP servers is blind LDAP Injection. It involves the user entering unfiltered values by the server into an LDAP query. Based on the response (true of false), we are able to determine whether the query given was valid. If it was, it means that the value we entered is also correct.

As an example, suppose we have a database of users. One of the application's functionalities is to display the user's non-sensitive data after accessing his account. Let's assume that their phone numbers are also stored in the database. The query directed to the LDAP server after accessing the user's profile looks like this:

(&(uid=12))
Enter fullscreen mode Exit fullscreen mode

As in the previous examples, let's append an additional string 12)(phonenumber=* to the id value. Thus, our created query is:

(&(uid=12)(phonenumber=*))
Enter fullscreen mode Exit fullscreen mode

Since the phonenumber field can take any value, the server will return true. Suppose the phone number of a user with id equal to 12 is 000-000-000.

(&(uid=12)(phonenumber=0*))
Enter fullscreen mode Exit fullscreen mode

By trial and error, we are able to guess (based on the server's response) the user's phone number. A similar attack was described in one of our previous posts.

How to defend yourself?

There are several ways to protect yourself. These include:

  • Filtering the data received and returned to the user (creating a whitelist and filtering the data based on regular expressions seems to be the easiest),
  • Using frameworks proven to automatically defend against LDAP Injection attacks,
  • Limiting the application's privilege to the necessary (principle of least privilege).

Sources

https://en.wikipedia.org/wiki/List_of_LDAP_software
https://www.openldap.org/doc/admin21/intro.html
https://bugspace.pl/phonebook-hack-the-box/
https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

Top comments (1)

Collapse
 
priteshusadadiya profile image
Pritesh Usadadiya

[[..Pingback..]]
This article was curated as a part of #113th Issue of Software Testing Notes Newsletter.
Web: softwaretestingnotes.com