lunes, julio 30, 2007

Blind SQL Injection (IV).
El Valor por Defecto

El problema del Conjunto Vacío (o cuál es el valor sin inyectar de referencia) en el análisis de un parámetro para averiguar si es vulnerable o no a SQL Injection y a explotación mediante Blind SQL Injection es muy importante. Tanto, que la elección del valor que utilicemos como conjunto vacío determinará que lleguemos a la conclusión correcta o a una conclusión errónea.

Para entender el problema analicemos un ejemplo. Tenemos una aplicación web con un programa que se llama programa.cod y de él, tras haber realizado un crawling (o recogida de todas las URLs de la web) tenemos un valor para uno de los parámetros que tenemos, digamos el parámetro id con el valor 1.

En resumen tenemos una URL del siguiente tipo:

http://www.miservidor.com/programa.cod?id=1

Y queremos saber si el parámetro id es vulnerable a SQL Injection explotable por Blind SQL Injection. Para ello probamos inyecciones de cambio de comportamiento 0 y de cambio de comportamiento negativo/positivo con los famosos:

http://www.miservidor.com/programa.cod?id=1 and 1=1
http://www.miservidor.com/programa.cod?id=1 and 1=0


¿Nos llevarán los resultados obtenidos a conocer si el parámetro es vulnerable o no?

Pues depende. Imaginemos, que el programador, ante la ausencia de resultados desde la base de datos muestra un valor por defecto. Si da la casualidad de que ese valor por defecto es justo el valor que tenemos, en este caso el valor 1 para el parámetro id no vamos a poder detectar la vulnerabilidad, ya que vamos a tener como respuesta algo que nos va a simular un parámetro seguro.

Jugando con el Primer Reto Hacking.

El código vulnerable allí era pista.aspx y el parámetro era id_pista. De este parámetro se daban dos valores, uno de ellos, el valor 1, era el valor por defecto, así que si intentabas encontrar la vulnerabilidad utilizando dicho valor, nunca llegarías a verla. Echemos un vistazo.

Primero sin inyección, el conjunto vacío:

http://www.informatica64.com/retohacking/pista.aspx?id_pista=1

Probamos ahora con la inyección and 1=1 para ver si podemos inyectar lógica:


http://www.informatica64.com/retohacking/pista.aspx?id_pista=1 and 1=1

Como se ve hemos obtenido la misma página de resultado, veamos ahora con la inyección and 1=2 para ver si obtenemos otra distinta.


http://www.informatica64.com/retohacking/pista.aspx?id_pista=1 and 1=2

Obtenemos la misma. Es decir, o es segura o estamos frente al parámetro por defecto y no vamos a poder saber si es vulnerable o no. Esto lo comprobamos introduciendo alguna Inyección No Valida, es decir, basura.


http://www.informatica64.com/retohacking/pista.aspx?id_pista=asd'asd

¿Quiere decir ésto que el parámetro es seguro? La respuesta es No. De hecho, si miramos con el valor 2 del parámetro, rápidamente se descubre la vulnerabilidad.


http://www.informatica64.com/retohacking/pista.aspx?id_pista=2

Y ahora probamos las inyecciones and 1=1


http://www.informatica64.com/retohacking/pista.aspx?id_pista=1 and 1=1

Y and 1=2


http://www.informatica64.com/retohacking/pista.aspx?id_pista=1 and 1=2

Y podemos comprobar la vulnerabilidad del parámetro. Esto es importante a la hora de comprobar la vulnerabilidad o no del mismo. La elección del valor por defecto. Analizaré más adelante como hacerlo con algunas herramientas de detección de vulnerabilidades, pero mientras. Una pregunta. ¿Qué pasa si no existiera ese valor 2? ¿Alguna otra solución?

Saludos!

13 comentarios:

Anónimo dijo...

Si sólo hay valor por defecto y la inyección es ciega (no devuelve errores la página), pues hay que buscar otra forma de poder "notar" si ha funcionado o no nuestra inyección. Por ejemplo, basándonos en tiempo:
... waitfor delay '0:0:5'
Aunque en el caso del reto I creo recordar que era un Access, no recuerdo de memoria si hay métodos similares para esta bd (estas son las cosas que se acaban mirando cuando te quedas atrancado en una parte del reto y por las que al final resulta fructífero, i.e., aprendes cosas).

-r

Chema Alonso dijo...

Mu bien, mu bien. Estás puesto, eh, pieza?

Anónimo dijo...

Ahora respóndame Vd., Sr. (e Ilmo.) Maligno:

¿Se te ocurre cómo hacerlo en el caso concreto del Reto I (=MS Access)? Ojo que no va con trampa, es que no recuerdo ahora mismo si hay algún truquillo para este caso... (para MySQL, p.ej, tienes benchmark pero para Access...).

-r

Chema Alonso dijo...

Pues no hay nada sobre el tema, pero sí que se puede conseguir de forma artesana realizando consultas complejas con las pocas tablas del catalogo que tiene, sin embargo la diferencia en tiempo es muy pequeña y se necesita una conexión de red con una latencia pequeñísima para poder sacarlo.

Anónimo dijo...

Hombre, esa opción siempre está ahí, pero es más o menos teórica; o en otras palabras, "unreliable", que dirían los guiris. ¿O no? }:-)

¿Algún PoC? Supongo que se podría hacer en 2 fases: la primera para calibrar tiempos, y la segunda para llevar a cabo la fuerza bruta basada en tiempos. ¿Alguna util que implemente esto de forma más o menos fiable?

-r

Chema Alonso dijo...

Yo jugando a mano lo he hecho con el wget que te marca tiempos, pero su precisión es muy baja, habrá que scriptar algo. mmmm. Comentaré con Rodol, a ver que se nos ocurre.

Anónimo dijo...

Hola:

Si ponemos como ejemplo el Reto I, yo no tengo tan claro que se tenga acceso a ninguna tabla del catálogo de Access desde la aplicación web.

Que yo sepa, si se usa una conexión de las típicas que se usan en .NET, te salta una excepción (por falta de permisos de lectura) al intentar acceder a la tabla MSysObjects.

Ya que habéis sacado el tema, ¿alguien me lo podría comprobar usando, por ejemplo, alguna condición del tipo "idPista=2 and (select count(*) from MSysObjects)>=0" ?

Un saludo

Chema Alonso dijo...

Hola señor Kachakil.

Se puede acceder, lo que pasa es que es un Access 2000 y no tiene las mimas tablas que el Access 2003, pero aquí tienes un acceso al catálogo.

http://www.informatica64.com/retohacking/pista.aspx?id_pista=2%20and%20exists%20(select%20*%20from%20MSysAccessObjects).

yo creo que haciendo una consulta pesada con la tabla contrasena, MsysAccessObjects y pistas, que son las tres tablas que se podían sacar, se puede intentar generar un retardo en Access. ¿medible? Esa es la cuestión.

Anónimo dijo...

Cierto, siempre me acabo liando con las tablas MSysAccessObjects y MSysObjects. A una se puede acceder y a la otra no (y la ley de Murphy hace que pruebes con la que no toca)

La verdad es que el tema es interesante. Probaremos a ver si sale algo, aunque de entrada parece complicado generar una consulta que tarde tanto como para diferenciar claramente el caso verdadero del falso (la BD tenía poquísimos datos). ¿Habrá que jugar con un poco de probabilidades y lógica difusa? ;-)

Un saludo

Chema Alonso dijo...

Sí, pero seguro que se nos ocurre algo. Yo una de las cosas que hice fue usar las funciones matemáticas, pero no se cual puede tardar mucho en access, ¿las raices cuadradas?. ¿Tal vez la raiz cuadrada del hash de la contraseña pasada a integer?

Anónimo dijo...

He encontrado una forma que parece funcionar al 100%! ;-)

Después de haber intentado de todo con las funciones matemáticas me he parado a pensar... ¿qué es lo peor que le puedes hacer a una BD a través consulta? Y la respuesta está en hacerle unas cuantas "natural join" que solamente se ejecutarán si todas las condiciones AND que la preceden son ciertas. Lógicamente, una de ellas debería ser la clave para hacer el Blind.

Cuando perfeccione el método, os lo comento con más detalle...

Un saludo

Chema Alonso dijo...

Buena, buena. Los IIS6 tiene URLScan activado, hay que encajarla en el espacio disponible!

Chema Alonso dijo...

Buena, buena. Los IIS6 tiene URLScan activado, hay que encajarla en el espacio disponible!

Entrada destacada

Seis recomendaciones personales de libros de @0xWord para disfrutar y aprender

Este verano pude disfrutar de la lectura de un libro que me encantó. El libro de Factfulness que me había regalado mi compañera Beatriz Ce...

Entradas populares