viernes, octubre 05, 2007

LDAP Injection & Blind LDAP Injection (Parte I de III)

********************************************************
Índice:
LDAP Injection & Blind LDAP Injection (Parte I de III)
LDAP Injection & Blind LDAP Injection (Parte II de III)
LDAP Injection & Blind LDAP Injection (Parte III de III)
********************************************************

Las técnicas de inyección de código se han utilizado para saltarse las restricciones de seguridad de las aplicaciones y sistemas, y, para logar este objetivo, se han especializado para afectar las distintas tecnologías. Una de las "últimas" en estudiarse han sido las técnicas de Inyección LDAP. De éstas la primera referencia que encontramos es la que nos ofrece Sacha Faust, de la empresa SPI Dynamics en su documento “LDAP Injection". El resto de artículos que se han publicado hacen siempre referencia a este mismo documento, convirtiéndolo casi en la única fuente documentada y pública de este tipo de técnicas. La mayoría de las publicaciones que hay sobre este tema referencian una y otra vez los mismos ejemplos publicados por Sacha Faust y las que no lo hacen aportan poco en el estudio de este problema.

LDAP

LDAP (lLightweight Directory Access Protocol) es un protocolo de acceso “ligero” a un directorio de servicios sobre TCP/IP. Inicialmente nació como una forma de consultar las bases de datos jerarquizadas de información en los árboles X.500 pero con el tiempo cobró entidad propia y hoy en día el directorio de información es un árbol LDAP. Con sus propias estructuras y documentos que formalizan esta tecnología. La versión actual está documentada por la RCF 4511, de Junio de 2006. El protocolo de acceso LDAP se utiliza para consultar y modificar los objetos almacenados.

Filtros LDAP

Es importante comprender el funcionamiento de los filtros LDAP, para ello, podemos consultar la RFC 4515 de Junio de 2006. En ella se adjunta la definición completa del leguaje de filtros, pero podemos resumirlo en la siguiente estructura:

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


Como se puede apreciar un filtro siempre va entre paréntesis. Además se dispone de un conjunto muy reducido de operadores lógicos AND “&”, OR “|” y NOT “!”, los operadores relacionales <=, >=, = y ~= y el comodín * que se utiliza para sustituir por a “uno o varios caracteres”. Así pues, ejemplos de filtros válidos serían:

- (&(!(objectClass=Impresoras))(uid=s*)): En este ejemplo estaríamos buscando todos los objetos que cumplan que no son de la clase Impresoras y cuyo atributo uid tiene un valor que comienza por “s”

- (&(objectClass=user)(uid=*)): Este filtro nos devolvería la lista de todos los objetos de tipo user, tengan el valor que tengan en el atributo uid.

No serían filtros válidos aquellos que no utilicen notación prefija del operador o no utilicen un anidamiento correcto de paréntesis, como por ejemplo:

- ((objectClass=Impresoras)|(nombre=Epson*)): En este ejemplo el operador lógico OR “|” no va correctamente situado.

- ((&(objectClass=Impresora))((nombre=Epson*Color)): En este caso los paréntesis no están bien anidados.

LDAP Injection en aplicaciones Web

Las técnicas de inyección de comandos LDAP en aplicaciones web se basan en los mismos principios que las técnicas de SQL Injection. En una aplicación web el programador, en un determinado punto recoge datos enviados por el usuario que van a ser utilizados para generar una consulta LDAP. En un entorno vulnerable el programador no realiza el filtrado de los parámetros y el atacante aprovecha este fallo de seguridad para poder inyectar código y cambiar el resultado que se obtiene con el filtro.

El ejemplo de vulnerabilidad explicada por Sacha Faust en su documento muestra un entorno en el que se extrae más información mediante la unión de un filtro. Para ello supone un entorno en el que el programador va a generar un filtro simple del tipo (atributo=valor). Entendemos filtro simple como aquel que no lleva un operador. Para ello construye una consulta mediante la concatenación del valor recibido convertido a cadena de caracteres que después ejecuta.

string: filter = "(uid=" + CStr(userName) + ")"

En este entorno, el atacante podría realizar una inyección de código LDAP para acceder a más objetos saltándose las restricciones del programa original. Siguiendo con el ejemplo de Sacha Faust, éste propone que se podría realizar una inyección de la siguiente forma: (some attribute=user input)(|(cn=*)). Para construir esta inyección, utilizando el código vulnerable habría que introducir como parámetro de entrada la siguiente cadena: sfaust)(|(cn=*)

sfaust” es la entrada de datos esperada por el programa para construir el filtro. Posteriormente, el atacante cierra el paréntesis que introduce el programador y abre un nuevo filtro con el operador lógico OR en el que se pide la devolución de todos los objetos sea cual sea su valor en cn.

Esta inyección, que Sacha Faust prueba sobre un árbol LDAP SunOne Directory Server 5.0 devuelve la suma de los resultados de los dos filtros: (uid=sfaust) y (|(cn=*)). Sin embargo, si nos ceñimos a la definición del lenguaje de creación de filtros marcada por la RFC vemos que esta consulta no es correcta pues los filtros no están siguiendo las normas de anidamiento y notación prefija. Sin embargo, sí podemos tomar la consulta como dos filtros independientes bien formados, aunque en segundo caso no sería necesario añadir el operador lógico OR. Probadas estas consultas sobre árboles ADAM y OpenLDAP vemos que NO devuelven más datos y por lo tanto este sistema de inyecciones NO puede ser utilizado con ellos.

Primeras conclusiones

Tras realizar estas pruebas podemos extraer las siguientes conclusiones:

1.- Para realizar una inyección de código LDAP en una aplicación que trabaje contra ADAM u OpenLDAP es necesario que el filtro original, es decir, el del programador tenga un operador OR o AND. A partir de este punto se pueden realizar inyecciones de código que permitan extraer información o realizar ataques Blind, es decir, a ciegas.

2.- En ese mismo entorno es necesario que la consulta generada tras la inyección esté correctamente anidada en un único par de paréntesis general o bien que el componente permita la ejecución con información que no se va a utilizar a la derecha del filtro.

“AND” LDAP Injection

En este entorno nos encontraríamos con que el programador ha creado una consulta LDAP con un operador AND y uno o los dos parámetros son solicitados al usuario y no está filtrado correctamente en servidor. En el caso de inyecciones en consultas LDAP que lleven el operador AND estamos obligados a utilizar el primer atributo algo válido, pero se pueden utilizar las inyecciones para mediatizar los resultados y por ejemplo, realizar escaladas de privilegios o acceso a otros objetos del árbol LDAP.

En este caso nos encontraríamos con una consulta del siguiente tipo:

(&(atributo1=valor1)(atributo2=valor2))

Ejemplos: Supongamos un entorno en el que se muestra la lista de todos los documentos a los que un usuario del nivel poco privilegiado tiene acceso mediante una consulta que incluye el directorio de documentos en un parámetro inyectable. Es decir, la consulta original es:

(&(directorio=nombre_directorio)(nivel_seguridad=bajo))

Un atacante podría construir una inyección del siguiente modo para poder acceder a los documentos de nivel de seguridad alto.

(&(directorio=almacen)(nivel_seguridad=alto))(|(directorio=almacen)(nivel_seguridad=bajo))

Para conseguir este resultado se habrá inyectado en el nombre del directorio la siguiente cadena: almacen)(nivel_seguridad=alto))(|(directorio=almacen

Como se puede ver, con esa inyección se han formado dos filtros correctamente formados pero los árboles ADAM y OpenLDAP devolverán sólo los resultados del primer filtro con lo que conseguiremos acceder a documentos, en este ejemplo, fuera de nuestra visibilidad incial.

“OR” LDAP Injection

En este entorno nos encontraríamos con que el programador ha creado una consulta LDAP con un operador OR y uno o los dos parámetros son solicitados al usuario:

(|(atributo1=valor1)(atributo2=valor2))

Supongamos en el ejemplo del árbol LDAP que tenemos una consulta inyectable del siguiente tipo: (|(cn=D*)(ou=Groups)) Es decir que devuelve todos los objetos cuyo valor en “cn” comience por “D” o cuyo valor en “ou” sea “Groups”. Al ejecutarla obtenemos:

Imagen: Consulta OR sin inyección

Si esta consulta sufriera una inyección de código en el primer parámetro, podríamos realizar una consulta que nos devolviera la lista de usuarios almacenados. Para ello realizamos la inyección en el primer valor de la siguiente cadena: void)(uid=*))(|(uid=*

Imagen: Lista de usuarios obtenida tras la inyección

Al formarse la consulta LDAP esta quedará construida de la siguiente forma: (|(cn=void)(uid=*))(|(uid=*)(ou=Groups)), permitiendo obtener, como se puede ver en la captura anterior la lista de todos los usuarios del árbol LDAP.

********************************************************
Índice:
LDAP Injection & Blind LDAP Injection (Parte I de III)
LDAP Injection & Blind LDAP Injection (Parte II de III)
LDAP Injection & Blind LDAP Injection (Parte III de III)
********************************************************

8 comentarios:

Anónimo dijo...

Se nota que sigues alentando a la gente a participar en el RH4, desgraciadamente soy de las personas que solo esta esperando la respuesta final...
¿Por que?
Por que no me interesa salir en el "salón de la fama" (aunque la verdad las personas que entren ahora debería darles mas pena que gloria) por que ya han salidos los que deben ganar.

No se por que aun nos sigues torturando con tantas pero tantas trabas, no se si es como dije sigues alentando gente o te haces al .... bueno mejor me ahorro lo que falta por que no vienen al caso :P.

Y ya por favor deja de torturarnos hay mucha gente que solo quiere ver la respuesta, por que ya pasado este tiempo y con tanto manojo de pistas, como explotar chapuzas y tutoriales (relacionados al reto) ya es una vergüenza pasarlo ( es ya mas grande que la vergüenza de decir no lo he pasado).

Saludos y excelente site/blog.
PD: por que solo pones cosas de la compañia spectra? que no te dejan hablar del pinguino y las chapuzas en este? ya me tiene un poco aburrido solo leer chapuzas para aplicables normalmente solo para los BlueHats.

Maligno dijo...

Hola Anónimo,

Realmente yo les aliento a que sigan participando en todos los retos. No es una competición de quién es el mejor, es un juego para aprender, por eso los premios tienen "esa calidad" ;)

Para mi es un regalo cuando alguien se pasa el reto (con solucionario y todo publicado) porque me siento agradecido de saber que a alguien le parece interesante y ha aprendido con él.

La competición "pura y dura" en el reto 4 acabó en seguida, pero lo bonito es aprender.

No quiero torturaros hombre, el solucionario (4 solucionarios a falta de uno) se van a publicar ya mismo, pero quiero dejar a la gente información antes para que aprendan. Yo creo que lo único malo es que no aprendamos todos. ;)

Gracias por la felicitación. Este blog nació como un "cachondeo anti-talibanes", pero hoy en día es un poco de cada cosa. De las "chapuzas" y las "supuestas chapuzas" en Spectra ya se hablan en otros sitos, así que ¿para que repetir la misma información?"

Saludos anónimo!

romansoft dijo...

@anónimo: yo publicaré mi solucionario al reto #4 en mi site (rs-labs.com) el lunes que viene (D.m).

@maligno: pa'que luego te quejes de que no soy un tipo obediente... :-*

-r

Maligno dijo...

Así me da tiempo a sacar primero el artículo y que la gente entienda mejor el porqué. Gracias Roman!

TheSur dijo...

Hola!, ¿El 5º juego cuando empezará?, creo recordar que dijiste que a principios de octubre. ¿Saldra este fin de semana? (¿Se puede saber la fecha o hay que estar en ascuas? jeje).

@Anonimo, yo creo que es mejor que antes de se publiquen las soluciones se den unas nociones basicas de la tecnologia usada y como se puede atacar, y asi luego poder entender con mas claridad el funcionamiento de la solucion.

pd: ¿Los videos del evento estan ya publicados?

Un saludo,
/Manu~

Anónimo dijo...

@maligno: gracias por responder, pero como te dije me están torturando (tanto que vengo diario o checho diario el RSS para ver si ya subieron el solucionario), sinceramente para mi el salón de la fama se debe congelar ya que los que están ahí (los 5 que lo pasaron en tiempo y forma) se lo merecen, los demas tambien pero es mas personal (relacionado al autoestima).
Ya estoy tan desesperao por el solucionario que toy apunto de sentarme a empezar el reto (ya que ni siquiera le he dado un vistazo, bueno talvez una mirada de esas rapidonas donde le di click mas rapido al salon de la fama de lo que tardo la web en cargarse) por que ya con tanta pista, tutorial ya debe ser refacil...
Sinceramente no he visto una web de "chapuzas" como la tuya que se hable con tanta gracia como profesionalismo sobre estas mismas y pues realmente soy lector de hace 3 dias y sinceramente se que trabajas para spectra y sus filiales pero que nos hablen de otras chapuzas fuera de las de Spectra por que el campo de la seguridad informatica se extiende a varios lados y en varios ambiente cambia, un ejemplo seria bueno que se hechen por ahi alguna movida sobre mac, por que tengo entendido que ahi las chapuzas son menores y esto es gracias a debido a la arquitectura que usan.

@romansoft: buaaahhhh hasta el lunes... talvez si le pido a butters que me despierte hasta el lunes por que si no me voy a morir de la desesperacion (sp 10x12 y 10x13).

@thesur: la mayoria ya esta en la red, como el texto de sacha en spy dinamics y los varios RFCs y texto sobre "hacking a LDAP", los solucionarios solo los estoy esperando por que no quiero sentarme a resolver un reto que ya para estos momentos no tiene dificultad mental, con tanta ayuda es como si te dejaran la llave de x casa tirada en frente de ti.

Saludos
PD: Me encantan los comentarios anonimos puede hechar piedras/flames sin sentirme obligado a revelar mi identidad muajajajajajajaja XD

Maligno dijo...

@TheSur, es a mediados, si todo va bien, para el finde después del pilar, es decir, el Viernes...19. ;). En cuanto estén los videos os indico dónde. Saludos!

@anónimo, el salón de la fama tiene fecha y hora asociado así que creo que no pasa nada. Además, si en boinas negras se pudo firmar siempre, yo creo que no está mal porque se pueda firmar en los retos y de verdad, que a mi me hace ilusión. De hecho, hay un caso de alguien a quien le tuve que forzar a firmar porque no quería y hay un par de ellos que han usado pseudonimos a sus nicks para que no les reconozcan. Yo os agradezco que si jugais, os lo pasais bien y os sirve para aprender algo firméis. De verdad. Petición expresa mia. ;)

El texto de Sacha no funciona ni con OpenLDAP ni con ADAM, esa era parte de la gracia del reto y del artículo que estoy publicando. Y el reto es tan fácil una vez que entiendes el artículo que te garantizo que puedes sacarlo sin solucionario.

Gracias por tus comentarios, y si vas a estar por aquí elige un nombre para que no te confundamos. Puedes seguir ocultando tu identidad, pero sabremos que eres tú.

;)

Anónimo dijo...

Interesante. Muy interesante.

Eleven Paths Blog

Seguridad Apple

Entradas populares