martes, enero 22, 2008

Time-Based Blind SQL Injection using Heavy Queries (Parte I de II)

***************************************************************************************
Artículo Publicado en la revista Hackin9 en Ene'08

- Time-Based Blind SQL Injection using Heavy Queries (I de II)
- Time-Based Blind SQL Injection using Heavy Queries (II de II)

***************************************************************************************

SQL Injection

OWASP (The Open Web Application Security Project) ha publicado recientemente un documento en el que recoge las 10 vulnerabilidades se seguridad más críticas en Aplicaciones Web. En él, se recogen las vulnerabilidades que más siguen afectando y que siguen siendo “viejas conocidas” para el gran público. En primer lugar se encuentran los ataques Cross-Site Scripting, con todas sus variantes de ataques persistentes y no persistentes mientras que en segundo lugar quedan las inyecciones de código malicioso y especialmente las vulnerabilidades de SQL Injection. Sí, parece que fue ayer cuando se publicó en el año 1998 el primer documento que hablaba de la posibilidad de inyectar código SQL en consultas firmado, por el ya famoso, rain.forest.pupy y titulado “NT Web Technology Vulnerabilities”, pues bien, ya casi 8años se cumplen desde que se habló de esa posibilidad y a día de hoy sigue siendo una de las vulnerabilidades más peligrosas.

Blind SQL Injection

Es cierto que las formas de explotarlas han ido cambiando, en parte, por la fortificación de sistemas, que, aunque no evita la vulnerabilidad si dificulta su explotación. En el año 2002 Chrish Anley hace referencia en su documento “(more) Advanced SQL Injection” a la posibilidad de realizar ataques de inyección de código a ciegas y utilizando métodos tan curiosos, en aquel entonces, como forzar una parada de tiempos en las bases de datos SQL Server si se cumple una condición llamando a un procedimiento almacenado para ejecutar un Ping a localhost o llamando a la función waitfor de Microsoft SQL Server. Fue en ese momento cuando se puede decir que ven la luz las técnicas de explotación de vulnerabilidades de inyección de comandos SQL a ciegas. Es decir, Blind SQL Injection.

En el año 2004, Cameron Hotchkies, en las Blackhat Conferences, presentando la herramienta SQueal, que más tarde se convertiría en Absinthe, hablaba de los métodos de automatizar la extracción de información mediante ataques Blind SQL Injection. El documento publicado “Blind SQL Injeciton Automation Techniques” mostraba las diferentes posibilidades a la hora de conocer cuando una respuesta significa un valor positivo o negativo. Se echa de menos en el documento y también en la herramienta la posibilidad mostrada por Chrish Anley de usar retardos de tiempo en la automatización.

Imagen: Extracción de datos con Absinthe

Time-Based Blind SQL Injection

A las técnicas que automatizan la extracción de información a ciegas usando retardos de tiempo se las conoce como Time-Based Blind SQL Injection y han ido especializándose en diferentes tecnologías de bases de datos para generar retardos de tiempo. Así, por ejemplo, la herramienta SQL Ninja, utiliza el sistema de tiempos descrito por Chrish Anley en aplicaciones web que utilizan motores de base de datos Microsoft SQL Server. Otras herramientas como SQL Power Injector utilizan el sistema de inyectar funciones Benchmark que generan retardos en motores de bases de datos MySQL o inyectar la llamada a la función PL/SQL DBMS_LOCK.SLEEP(time) en sistemas con motores Oracle. Para otros sistemas de bases de datos como Access o DB2 no existe forma similar de generar retardos de tiempo. Los métodos de generar estos retardos de tiempo quedan por tanto restringidos bastante. En primer lugar para Access, DB2 y otros motores de bases de datos no se conoce ninguna forma; en segundo lugar, para hacerlo en motores Oracle se necesita acceso a una inyección PL/SQL que no es común encontrarse con un entorno que lo permita y, por último los sistemas de fortificación suelen tener en cuenta la restricción del uso de funciones Benchmark en entornos MySQL y waitfor en entornos Microsoft SQL Server.

En el presente artículo vamos a ver como poder realizar un ataque a ciegas usando inyecciones de código que generan retardos de tiempo utilizando consultas pesadas, es decir, Time-Based Blind SQL Injection with Heavy Queries.

“Booleanización”

El término “Booleanización” no es mío, la primera vez que lo leí fue en el documento “Blind XPath Injection” de Amit Klein y que desconozco si existía previamente o no, pero en el caso de que no existiera hay que crearlo. La idea consiste en como extraer un dato mediante una secuencia de condiciones booleanas que devuelve True o False. Por ejemplo, supongamos queremos extraer el valor del campo username de la vista all_users en un motor Oracle y este valor es “sys”. El proceso de “booleanización” sería el siguiente:

255>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> True [255 > ASCII(‘s’)=115]

122>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> True [122 > ASCII(‘s’)=115]

61>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> False [61 < ASCII(‘s’)=115]

92>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> False [92 < ASCII(‘s’)=115]

107>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> False [107 < ASCII(‘s’)=115]

115>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> False [115 = ASCII(‘s’)=115]

119>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> True [119 < ASCII(‘s’)=115]

117>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> True [117 < ASCII(‘s’)=115]

116>(Select ASCII(Substr(username,1,1)) from all_users where rownum<=1
-> True [116 < ASCII(‘s’)=115]

En este punto se ha averiguado que el valor ASCII de la primera letra del nombre es 115 ya que no es mayor que 115 y es menor que 116. Y se pasaría a realizar el mismo proceso con la segunda letra. Como se puede ver el proceso va a exigir una serie de repetición de peticiones para cada valor, pero al final se obtiene el resultado. El problema, como se explica al principio de este artículo, es determinar cuando la respuesta es True y cuando es False.

Time-Based Blind SQL Injection

Hasta el momento, lo sistemas que se conocían para extraer información estaban basados en las funciones que ofrecía cada motor de bases de datos, así, por ejemplo, en una aplicación web que utilice Microsoft SQL Server podría realizarse una inyección como la siguiente:

http://servidor/prog.cod?id=1; if (exists(select * from contrasena)) waitfor delay ‘0:0:5’--

Esta consulta, en el caso de existir la tabla “contrasena” y tener algún registro va a pausar la respuesta de la página web un tiempo de 5 segundos. Si la respuesta se obtiene en un periodo inferior podemos inferir que la tabla “contrasena” existe y tiene algún registro. La misma idea puede ser utilizada para una aplicación con Oracle:

http://servidor/prog.cod?id=1; begin if (condicion) then dbms_lock.sleep(5); end if; end;

Y con MySQL, usando por ejemplo la función Benchmark del ejemplo, que suele tardar unos 6 segundos en procesarse o la función Sleep(), que ya viene en las versiones 5 de MySQL.

http://servidor/prog.cod?id=1 and exists(select * from contrasena) and benchmark(5000000,md5(rand()))=0

http://servidor/prog.cod?id=1 and exists(select * from contrasena) and sleep(5)

Heavy Queries

Las consultas pesadas han sido y siguen siendo un quebradero de cabeza en la optimización de sistemas de bases de datos. Un motor puede almacenar cantidades de información tan grandes y con tal cantidad de usuarios que si no se optimizaran las bases de datos dejarían de ser útiles. Los ajustes de rendimiento son constantes en los grandes sistemas de bases de datos para conseguir mejorar los tiempos de respuesta. Con los años los motores de bases de datos se han ido evolucionando para que sean ellos los que optimicen las consultas que generan los programadores y no al revés como se hacía antaño, aunque hay algunos motores que siguen requiriendo del programador para optimizar una consulta. Es decir, supongamos una consulta Select como la siguiente:

Select campos from tablas where condición_1 and condición_2;

¿Con que orden evaluar las condiciones para que se ejecute esta consulta y el sistema lo más rápido posible? En este ejemplo, al utilizar una condición AND, si la primera condición que evaluamos da como resultado un valor FALSO el motor ya no tiene que evaluar la otra. Si hubiera sido un operador OR el funcionamiento hubiera sido al revés, es decir, si la primera da VERDADERO ya no hay que evaluar la segunda condición. La conclusión varía en cada motor de bases de datos. En algunos se establece una precedencia y se hace recaer la optimización sobre el programador. Es decir, se evalúan las condiciones de izquierda a derecha o de derecha a izquierda y es responsabilidad del programador elegir el orden de evaluación en función de la probabilidad de obtener el resultado en menos tiempo. Si por ejemplo se estima que en evaluar la condición_1 el motor tarda 6 segundos y en evaluar la condición_2 unos 2 segundos y el motor utiliza precedencia por la izquierda entonces habrá que situar a la izquierda la condición de menos tiempo. Para entenderlo vamos a ver la tabla de tiempos posibles:

Tabla con la condición_1 (la pesada) a la izquierda
Tabla con la condición_2 (la ligera) a la izquierda

Como se puede ver, en una probabilidad similarmente distribuida de que cada condición pueda tomar valores TRUE o FALSE, es más optimo evaluar siempre primero la consulta ligera. Esto puede cambiar en función de las densidades. Es decir, en una clausula Where con operador AND en la que la condición ligera tenga una probabilidad del 99 % de ser TRUE y la pesada una probabilidad del 5 % de ser TRUE puede ser más eficiente utilizar una precedencia distinta.

Motores como Microsoft SQL Server u Oracle implementan optimización de consultas en tiempo de ejecución. Es decir, analizar las condiciones que pone el programador y eligen el orden de ejecución “correcto” según su estimación. Para ello utilizar reglas básicas, avanzadas e incluso datos estadísticos de las tablas de la base de datos en concreto.

***************************************************************************************
Artículo Publicado en la revista Hackin9 en Ene'08

- Time-Based Blind SQL Injection using Heavy Queries (I de II)
- Time-Based Blind SQL Injection using Heavy Queries (II de II)

***************************************************************************************

8 comentarios:

SealTeam dijo...

Si es que estoy aprendiendo mas leyendo tu blog que atendiendo en clase...
Espero que no pases mucho frío y que encuentres un huequecito todos los días para seguir posteando.
Por cierto ¿sabes si va a ver algún evento de microsoft en Valladolid este año?

Pedro Laguna dijo...

Por aqui han usado algo de consultas pesadas... http://reddit.com/info/660oo/comments/

Troxer dijo...

[OFFTOPIC]
Como este era post de "no pelearse con nadie", para cuando toque post de pelea, acuérdate de IBM, de cómo apoya ODF por el bien de la humanidad y el SL, y de cómo ha decidido no liberar OS/2.

Luego la mala es Spectra

Dark_TuxVAder dijo...

@troxer...

Uuuuum veo ganas de guerra!!
Y de esta vuelta, la verdad es que voy a callar porque la verdad es que me toca los cojones un poco.

Pero bueno tambien me los toca de la misma forma que gente que no vive de M$ ni nada la defienda como santoPatrón, no lo entiendo no os regala nada coño...

Hace tiempo me apunte al movimiento floss, y hay sigo pero nunca lleve como mía la bandera de IBM, ni de Google, ni siquiera de Red Hat; Oyes que por ciertas causas en ocasiones hacen cosas que pienso que son buenas para la 'comunidad' pues cojonudo les aplaudo pero de la misma manera les crítico cuando no es así.

Por cierto... una entrada cojonuda!

Alex dijo...

@Dark_TuxVAder:
Aléjate del lado del mal o acabarás cayendo en el. ;P

Muy buena la publicación Chema!

Troxer dijo...

@Dark_TuxVader

Como has dicho "os regala", me daré por aludido. No, no me regala nada, pero es que NO, no he defendido a Microsoft con ese comentario, sino criticado a IBM y, SOBRETODO, a todos los pringados que aceptan ODF a pies juntillas, chillan contra OpenXML y no se dan cuenta que no son más que marionetas de compañías como IBM, que se dice "libre" y partidaria del SL cuando sólo es partidaria de si misma.

Por mí, que haya ODF, OpenXML y cualquier cosa que me beneficie como desarrollador (que de eso vivo) y como usuario. Consideraciones morales a /dev/null (como os gusta decir a vosotros).

Anónimo dijo...

Hola maligno. Perdona, pero tengo dos dudillas:

- Que es una parada de tiempos en una BBDD

- A que ayuda en blind sql inyection usar retardos de tiempo en la automatización.

Gracias y un saludo.

Maligno dijo...

@Anonimo,

- Una parada de tiempos es un retardo en contestar de la base de datos.

- Las técnias de blind son más automatizables pq no dependen en dónde devuelva la información el servidor dentro de la página respuesta. Basta buscar dos respuestas diferentes (Verdad/Falso) y el resto es lógica binaria.

Saludos!

Entradas populares