miércoles, febrero 13, 2008

Arithmetic Blind SQL Injection

Hace tiempo, en un test de intrusión no autorizado, que eufemismo más chulo para decir que estaba haciendo…otra cosa, me encontré con un problema que me costó resolver. El entorno era el siguiente:

- Una base de datos Access en la que no podía poner comentarios.
- Una consulta en la que el parámetro inyectable estaba dentro de una función matemática que exigía como dato de entrada un número.
- Se usaba ese parámetro en dos condiciones where con distintos grados de anidación de paréntesis.

Vamos, era algo como:

Select campos
From tablas
Where (abs(parámetro_inyectable)=número) and abs(parámetro inyectable)=numero


Encontrar una cadena de inyección que construyera una consulta SQL correcta saliéndose de los paréntesis era completamente imposible pues si inyectabas algo del tipo: 1) and 1=1 and (abs(1 se obtenía algo como: Where (abs(1) and 1=1 and (abs(1 )=número) and abs(1) and 1=1 and (abs(1 )=numero

Quedaba perfectamente construida la query en la primera condición, pero no en la segunda. Y si inyectaba otra cadena que hiciera correcta la segunda query en paréntesis, la primera quedaba mal construida.

Bien, parecía imposible salir de la función matemática en la que estaba enjaulado. Así que había que hacer una lógica sin salirse de allí. Probé el método descrito por Litchfield en alguno de sus docs de hacer una lógica basándose en la división por 0, es decir, forzar que si algo era cierto diera división por cero. Es decir, el parámetro inyectable tenía que ser un número, entonces hagamos que la inyección siempre devuelva un número… o un error matemático.

parámetro_inyectable =if ((select user) = 'sa' OR (select user) = 'dbo') select 1 else select 1/0

Bueno, en Access no hay if, así que así no valía, había que realizar operaciones matemáticas a manopla para generar la división. Sin embargo, el método de la división por cero está bien cuando hay un if de por medio y cuando además el error es visible, pero… ¿por qué generar un error si podemos jugar con las mátematicas?

ensemos en el típico sistema de noticias dónde tenemos algo como noticias.php?id=14567 dónde queremos sacar, por ejemplo, la password del administrador de una supuesta tabla users.

- Si ponemos noticias.php?id=14567 obtenemos la Noticia 1
- Si ponemos noticias.php?id=abs(14567) y obtenemos la Noticia 1 entonces el sistema es inyectable.
- Si ponemos noticias.php?id=14566 obtenemos otra noticia.
- Si ponemos noticias.php?id?14567+60-(select ascii(mid(password,1,1)) from users) obtendremos la Noticia 1 si el primer caracter de la password es el que tiene ASCII 60 si no obtendremos otra noticia.

Esta forma de hacer un ataque por Blind SQL Injection permite no preocuparse por las anidaciones de paréntesis, no generar un error de división por cero (que puede tirar la sesión de la aplicación o generar una alerta XXL en la base de datos y además… funciona para todas las inyecciones con valores numéricos… Sencillo ¿no?

Saludos Malignos!

PD: ¿No quieres jugar con el Reto VI?

19 comentarios:

kabracity dijo...

Simplemente genial, cada vez me da más miedo todo lo relacionado con las bases de datos!

Por cierto creo que en el curro quieren usar Joomla, lo único que recuerdo es un post en el que hiciste referencia a vulnerabilidades de Joomla (creo que la web del Getafe por ejemplo).
Ha mejorado la cosa, o sigue teniendo agujeros grandecitos?

Un Saludo!

Anónimo dijo...

Los tenía, habrás sido corregidos, pero volveran a aparecer fallos si siguen haciendolo igual de bien. échale un vistazo a securityfocus por ejemplo para ver los fallos que van apareciendo.

ANELKAOS dijo...

Buenas, melenas jeje

Ya tienes metida tu charla en el boletín de este mes de elhacker.net 6.650 usuarios mas que se enteran.

Nos vemos!

Joselopez dijo...

@kabracity: Dile a tu jefe que se inscriba y mire una semanita la lista de FDisclosure,Bugtraq y Shhackers que veras como cambia de opinion en cuanto a implementar Joomla como solucion web. :P

Anónimo dijo...

Por cierto el de arriba era yo que se ha posteado con la cuenta de google!

summun dijo...

La de cosas que se aprenden aquí, muy bueno el post. Pensamiento lateral a saco.
Hasta que nos olamos!

Anónimo dijo...

A pesar de que Access no admite comentarios en las consultas, con un poco de suerte se puede llegar a tragar el carácter nulo (%00 en una URL) como terminador de cadena, ignorando todo lo que aparezca después de dicho carácter.

Es cierto que no siempre funciona, pero tampoco se pierde nada intentándolo, así que tomad nota, que alguna vez os será útil.

Y si no funciona, pues a practicar con el Reto VI, como bien dice Chema... ;-)

Saludos!

Anónimo dijo...

yo me cago en access

Anónimo dijo...

lol, mas pistas no se pueden...
Ya como dicen por ahi, si no lo ves comprate un par de lentes.

Creo que el chema esta aburrido/desesperado al solo falta 1 para que se acabe el torneo , ya que hay mas de 100 dormidos en la parte 1 solo esta penyaksito en la segunda fase.

Anónimo dijo...

Casi todo bien, excepto que estás partiendo de la idea que conoces la consulta, cómo está construida. Eso no se tendría porque saber, ¿no?

kabracity dijo...

@sirw2p le echaré un vistazo a las listas, asias :).Tienen a alguien que no se maneja en php para hacer la web y creo que ha querido tirar por el camino fácil..lo malo que a veces lo fácil se puede pagar caro a la larga :/

@anónimo no tienes por qué saber como es exactamente la consulta al principio, pero probando empiezas a descartar, a ver qué tipo de parámetros acepta, y quizás no llegues a la consulta exacta pero te haces una idea de por donde van los tiros y por donde puedes atacar digamos

Anónimo dijo...

No, no hes necesario conocer la query...

Realmente primero debes concentrarte en conseguir los estados (cuando es error, cuando falso y cuando verdadero).

Ya luego de eso te concentras en la inyeccion, sirve de mucho que te hagas una BD para practicar en casa...

Anónimo dijo...

Por ahora tengo cuando es error y cuando es falso, me faltaría encontrar el estado verdadero :)

A ver si luego lo consigo.

Trancek dijo...

joder si que existen cosas raras en inyecciones xDD, yo si k me pierdo ahi por algo me kede en el VI, y para kien le de da pistas aki tmb sobre el reto :P

Anónimo dijo...

Cuando dices conocer los estados error, verdadero y falso. ¿qué quieres decir?

Tal como lo tengo ahora:
- Tengo una query con 2 estados válido e inválido, de esta manera puedo acotar. El problema es que no se como acotar sin tablas, ni campos ni nada!

- Tengo otra manera basada en la anterior que me da un error 500. ¿esto es normal? o es que me ha salido el tiro por la culata?

Creo que la primera manera es la correcta (me dice si el valor es correcto/incorrecto o no válido). Lo otro creo que es algo que ha salido de casualidad.

Hora de dormir, mañana mmas y mejor (esperemos)

Anónimo dijo...

Pues es meramente simple, recuerda que los ataques Blind se basen en verdadero y falso, en este caso el chema para hecharnos una manita (y tambien como una ligera pista) nos ha puesto uno de error.

Cuando llegas al reto te encuentras con 2 estados el falso y el error que bien aplicando la regla digamos solo te quedas 1 (el falso)...

Tu labor o la primera parte de la que las hable anteriormente es encontrar este estado verdadero, que si bien he visto que no es necesario este mismo para elaborar la inyeccion (ya que puedes hecharte una logica un poco rarita y jugar con el error como falso y verdadero el falso) si lo encuentras te ahorra muchos problemitas...

Si quieren una pistilla sobre este les recomiendo leer sobre los enteros o bien el tipo de dato entero eso les servira si andan muy perdidos.

Saludos

Anónimo dijo...

"echarte una logica un poco rarita y jugar con el error como falso y verdadero el falso) si lo encuentras te ahorra muchos problemitas..."

Eso es lo que intentaba anoche sin mucho éxito. A ver si al mediodía tengo tiempo de seguir probando.

Saludos

Anónimo dijo...

Estoy más que perdido... aunq nunca pretendí no estarlo.

Ponga la consulta que ponga me devuelve el mensaje de error. Supongo que he construido mal la inyección, pero por probar estoy haciendolo con cosas simples y que siempre deberían devolver un valor numérico y no tira ni a la de 3...

Tendré que resignarme a esperar la solución, aunq he de decir que el descifrar las pistas está siendo entretenido.

Anónimo dijo...

"Uy que cerca, casi estás garrupintizado!"

Me he emocionado

Entrada destacada

10 maneras de sacarle el jugo a tu cuenta de @MyPublicInbox si eres un Perfil Público

Cuando doy una charla a algún amigo, conocido, o a un grupo de personas que quieren conocer MyPublicInbox , siempre se acaban sorprendiendo ...

Entradas populares