| Artículos | 01 NOV 2007

Técnicas avanzadas en inyección de SQL a ciegas

Tags: Actualidad
Chema Alonso.

"Durante los meses de junio y julio, PC World publicó un par de artículos orientados a comprender las técnicas de ataques basado en inyecciones ciegas, detectar las vulnerabilidades manualmente o mediante el uso de escáneres y mitigar el impacto de un ataque no detectable. Estas técnicas se han extendido mucho en la actualidad, por lo que cada vez es más común ver exploits que hacen uso de este tipo de ataques. En esta ocasión vamos a dar un paso más, desvelando las técnicas más avanzadas de este tipo de ataques.
Se puede comprobar los últimos exploits para aplicaciones web publicados en diferentes sitios de internet y comprobar cómo las técnicas más usadas son RFI (Remote File Inclusion) y SQL Injection (en todas su vertientes) son de las más populares.
Debido al interés suscitado y al creciente número de incidencias basadas en técnicas de inyección de código, hemos decidido volver a tratar el asunto, aunque a través de dos variantes muy especiales. La primera consiste en utilizar inyecciones ciegas de comandos SQL para extraer ficheros del sistema operativo; es decir, para poder sacar un fichero almacenado en el servidor sobre el que está corriendo el motor de la base de datos. La segunda consiste en realizar inyecciones que retrasen la respuesta del motor de base de datos para conocer, en base a su respuesta, la información que nos interesa obtener.
Breve repaso a Blind SQL Injection
Para los que no hayan leído los artículos dedicados Blind SQL Injection, o para aquellos que necesiten refrescar la memoria, vamos a describir brevemente el funcionamiento de la técnica de ataque. La idea fundamental se basa en que un entorno es una aplicación web que recibe datos desde el cliente. Estos datos se utilizan para construir una consulta a la base de datos para extraer información. Por lo tanto, este tipo de ataque envía comandos SQL cuando la aplicación es vulnerable a técnicas de inyección SQL (pero nunca puede acceder a los resultados que devuelve la consulta porque la aplicación no los imprime). Sin embargo, en estos casos, para obtener la información que estamos buscando, siempre se puede apreciar un comportamiento distinto ante consultas que devuelven datos y consultas que no lo hacen. A partir de este comportamiento distinto se intenta inyectar lógica para extraer la información en base a valores True o False.
Como se puede apreciar en el ejemplo que publicamos el pasado mes de julio (que se muestra en la imagen1), no es necesario ser un programador experimentado para entender su funcionamiento, aunque sí vamos a ver un poco de código.
El objetivo de este exploit es inyectar una cadena SQL que acceda a la tabla donde se almacena la contraseña del administrador. En la línea 7 (en color azul), se puede ver que la cadena que va a inyectar accede al campo admin_pw de la tabla se_games para obtener la contraseña. Sin embargo, esta cadena no devuelve el valor del campo, pues la aplicación web no va a mostrar ese resultado por pantalla nunca. En este caso, el atacante resuelve el problema generando un retardo de unos 5 ó 6 segundos llamando a la función Benchmark, únicamente cuando el valor ASCII del carácter de la contraseña que se encuentra en la posición $j es igual al valor $i, que va recorriendo todo el alfabeto ASCII.
Esto le permitirá al atacante averiguar cada uno de los caracteres que componen el hash de la contraseña del usuario administrador. Más adelante, de la línea 8 a la 15 se realiza la construcción del paquete que se va a enviar al servidor web y puede comprobarse en la línea 13 cómo la inyección se realiza en el campo USER AGENT del mismo. Esto es bastante curioso, pero hay que recordar que cualquier dato que venga desde el cliente y que vaya a ser utilizado en una consulta a la base de datos es potencialmente peligroso. Esto nos indica que, por alguna razón, el servidor web está guardando estadísticas de los clientes que navegan por el sitio web en una base de datos. En este caso, esta medida es tan peligrosa que incluso puede suponer la extracción de la contraseña.
La medición del retardo se puede ver resaltada en color rojo (en la línea 6 se toma el tiempo antes de lanzar el paquete, se envía en la línea 16 y en la sentencia 17 se toma el tiempo después de llegar la respuesta). Posteriormente, se calcula la diferencia de tiempo y, si ésta es mayor de 7 segundos, entonces se concluye que el valor ASCII del carácter de la contraseña que se encuentra en la posición $j es igual al valor $i. Una vez averiguado ese carácter, el exploit continúa a por el valor de la siguiente posición sucesivamente hasta obtener la cadena completa.
En este caso hemos visto cómo se puede realizar un ataque de Blind SQL Injection basado en tiempos generando retardos usando una función intensiva en cálculo de MySQL. No obstante, para cada motor de base de datos existen formas distintas de generar retardos de tiempo. En SQL Server, por ejemplo, se utiliza la función waitfor, en Oracle usando la llamada a DBMS_Lock y en MySQL usando las funciones Benchmark, como en el exploit de ejemplo o con la función sleep en las versiones 5 (Imagen2).
Sin embargo, éstas no son las únicas opciones para la generación de retardos de tiempo en ataques a ciegas.
Inyección en base a tiempos usando consultas pesadas
En base a lo que acabamos de ver, algún avezado lector podría pensar que si nuestra infraestructura no permite el acceso a las funciones enumeradas anteriormente no se podrá realizar nunca un ataque a ciegas basado en tiempos, pero esto no es cierto. El problema sigue persistiendo, ya que el verdadero fallo de seguridad sigue siendo el mal filtrado de los datos que van a ser utilizados en la construcción de una sentencia SQL y que van a poder ser explotados. Supongamos, por ejemplo, un entorno en el que las páginas de error no difieren de las auténticas, es decir, que aunque se genere una inyección no se aprecia ningún cambio medible entre las páginas True y False. Además, para reforzar la seguridad, se han anulado las funciones enumeradas anteriormente, por lo que parecería imposible medir un retardo de tiempo en el comportamiento de una aplicación ante una inyección SQL. Sin embargo, en este caso esto sigue siendo posible realizar este tipo de técnicas, ya que, en el modelo que planteamos, un atacante todavía puede inferir información mediante técnicas a ciegas usando consultas pesadas, que hagan trabajar al motor de bases de datos y, por tanto, generen retardos de tiempo ante respuestas positivas.
Supongamos, por ejemplo, una aplicación web que utiliza una base de datos Microsoft Access y que ésta tiene un fallo de inyección SQL que únicamente puede ser explotado a ciegas. Los motores de Microsoft Access no tienen funciones de retardo, lo que nos llevaría al caso que planteamos: ¿cómo generamos un retardo de tiempo ante respuestas positivas?
En la siguiente URL el parámetro vulnerable es id_pista y deseamos saber si existe la tabla contrasena.
www.servidor.com/pista.asp?id_pista=1
Aquí, para averig

Contenidos recomendados...

Comentar
Para comentar, es necesario iniciar sesión
Se muestran 0 comentarios
X

Uso de cookies

Esta web utiliza cookies técnicas, de personalización y análisis, propias y de terceros, para facilitarle la navegación de forma anónima y analizar estadísticas del uso de la web. Consideramos que si continúa navegando, acepta su uso. Obtener más información