lunes, julio 02, 2007

Protección contra las técnicas de Blind SQL Injection (I de IV)

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

Aprovechando que estaba trabajando con las técnicas de Blind SQL Injection, en las revistas de Junio (partes I y II) y Julio (partes III y IV) de PCWorld escribí unos artículos sobre como protegerse (¿?) contra las técnicas de Blind SQL Injection. Los publicaré en cuatro entregas. Espero que os entretengan.

***************************************************************************************
Protección contra las técnicas de Blind SQL Injection (I de IV)
Protección contra las técnicas de Blind SQL Injection (II de IV)
Protección contra las técnicas de Blind SQL Injection (III de IV)
Protección contra las técnicas de Blind SQL Injection (IV de IV)
***************************************************************************************

Saludos!
*********************************************************************************

Tienes más info en los posts sobre Blind SQL Injection y recuerda que el primer Reto fue sobre Blind.

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

SQL Injection, ese “viejo amigo”

No llevan tantos años entre nosotros las técnicas de SQL Injection para atacar a aplicaciones web y parece que lleven toda la vida. En esto de la tecnología siempre sucede esto, parece que llevo utilizando servidores Windows 2003 de siempre y resulta que no llevo tanto y [chiste malo] si te paras a pensar resulta que en Barcelona 92, en las olimpiadas, aún no había salido Windows 95 [/chiste malo].

Con las técnicas de SQL Injection sucede algo similar, fue rain.forest.puppy en el Phrack Magazine Volumen 8, Número 54 del 25 de Diciembre de 1998, una publicación realizada por la comunidad y para la comunidad de Internet, quién publicó un artículo titulado “NT Web Technology Vulnerabilities” en el que analizaba las posibilidades de la inyección de código SQL en aplicaciones ASP y motores de bases de datos SQL Server 6.5 aunque en ese momento no se llamaba SQL Injection, el le llamaba algo así como “añadir consultas”. Poco después hackearía la web PacketStorm utilizando estas técnicas, y lo explicaría en un documento que se llamaba “How i Hacked PacketStorm”. No se llamaría aún SQL Injection, es más, el nombre de SQL Injection no lo recibiría hasta el día 23 de Octubre de 2003 en la web SQLSecurity.com, Chip Andrews, publicara “SQL Injection FAQ”.

A partir de ese momento las posibilidades han sido estudiadas en profundidad en diferentes artículos y manuales disponibles en la web. Dignos de citar esos documentos, si quieres realmente saber como pueden afectar a cualquier aplicación web son recomendables los siguientes:

La primera buena discusión sobre los riesgos de diseñar aplicaciones sin protección contra SQL Injection la escribió David Litchfield de NGS Softweare, en el año 2001 con el nombre de “Web Application Disassembly with ODBC Error Messages”.

“Advanced SQL Injection en Microsoft SQL Server”, publicado el año 2002 por Chrish Anley de NGS Software y la segunda, y aún mejor parte “(more) Advanced SQL Injection” del mismo autor y publicada en Junio del mismo año.

Digno de citar es también el estudio de Cesar Cerrudo, de la empresa Application Security, que fue publicado en el mes de Agosto de 2002 y con el título “Manipulating Microsoft SQL Server using SQL Injection”.

¿Puestos al día con SQL Injection? Pues vamos un poco más allá con ello.

Blind Sql Injection

Una de las formas de realizar estos ataques se basa en ataques a ciegas, es decir, en conseguir que los comandos se ejecuten sin la posibilidad de ver ninguno de los resultados. La inhabilitación de la muestra de los resultados del ataque se produce por el tratamiento total de los códigos de error y la imposibilidad de modificar, a priori, ninguna información de la base de datos. Luego, si no se puede alterar el contenido de la base de datos y no se puede ver el resultado de ningún dato extraído del almacén, ¿se puede decir que el atacante nunca conseguirá acceder a la información?

La respuesta correcta a esa pregunta, evidentemente, es no. A pesar de que un atacante no pueda ver los datos extraídos directamente de la base de datos sí que es más que probable que al cambiar los datos que se están enviando como parámetros se puedan realizar inferencias sobre ellos en función de los cambios que se obtienen. El objetivo del atacante es detectar esos cambios para poder inferir cual ha sido la información extraída en función de los resultados.

La forma más fácil de automatizar para un atacante esta técnica es usar u vector de ataque basado en lógica binaria, es decir, en Verdadero y Falso. Este es el vector de ataque que va a centrar todo el estudio del presente proyecto, las Técnicas de Inferencia Ciega basada en Inyección de Comandos SQL.

El parámetro vulnerable

El atacante debe encontrar en primer lugar una parte del código de la aplicación que no esté realizando una comprobación correcta de los parámetros de entrada a la aplicación que se están utilizando para componer las consultas a la base de datos. Hasta aquí, el funcionamiento es similar al resto de técnicas basadas en inyección de comandos SQL. Encontrar estos parámetros es a veces más complejo ya que, desde un punto de vista hacker de caja negra, nunca es posible garantizar que un parámetro no es vulnerable ya que tanto si lo es, como si no lo es, puede que nunca se aprecie ningún cambio en los resultados aparentes.

Hagamos una definición, definamos el concepto de “Inyección SQL de cambio de comportamiento cero” (ISQL0) como una cadena que se inyecta en una consulta SQL y no realiza ningún cambio en los resultados y definamos “Inyección SQL de cambio de comportamiento positivo” (ISQL+) como una cadena que sí provoca cambios.

Veamos unos ejemplos:

Supongamos una página de una aplicación web del tipo:

http://www.miweb.com/noticia.php?id=1

Hacemos la suposición inicial de que 1 es el valor del parámetro id y dicho parámetro va a ser utilizado en una consulta a la base de datos de la siguiente manera:

Select campos
From tablas
Where condiciones and id=1


Una inyección ISQL0 sería algo como lo siguiente:

http://www.miweb.com/noticia.php?id=1+1000-1000
http://www.miweb.com/noticia.php?id=1 and 1=1
http://www.miweb.com/noticia.php?id=1 or 1=2


En ninguno de los tres casos anteriores estamos realizando ningún cambio en los resultados obtenidos en la consulta. Aparentemente no.

Por el contrario, una ISQL+ sería algo como lo siguiente

http://www.miweb.com/noticia.php?id=1 and 1=2 (a estas las llamo ISQL- ¿está claro por qué?)
http://www.miweb.com/noticia.php?id=-1 or 1=1
http://www.miweb.com/noticia.php?id=1+1


En los tres casos anteriores estamos cambiando los resultados que debe optener la consulta. Si al procesar la página con el valor sin inyectar y con ISQL0 nos devuelve la misma página se podrá inferir que el parámetro está ejecutando los comandos, es decir, que se puede inyectar comandos SQL. Ahora bien, cuando ponemos una ISQL+ nos da siempre una página de error que no nos permite ver ningún dato. Bien, pues ese es el entorno perfecto para realizar la extracción de información de una base de datos con una aplicación vulnerable a Blind SQL Injection.

¿Cómo se atacan esas vulnerabilidades?

Al tener una pagina de “Verdadero” y otra página de “Falso” se puede crear toda la lógica binaria de las mismas.

En los ejemplos anteriores, supongamos que cuando ponemos como valor 1 en el parámetro id nos da una noticia con el títular “Raúl convertido en mito del madridismo”, por poner un ejemplo y que cuando ponemos 1 and 1=2 nos da una página con el mensaje Error. A partir de este momento se realizan inyecciones de comandos y se mira el resultado.

Supongamos que queremos saber si existe una determinada tabla en la base de datos:

Id= 1 and exists (select * from usuarios)

Si el resultado obtenido es la noticia con el titular de Raúl, entonces podremos inferir que la tabla sí existe, mientras que si obtenemos la página de error sabremos que o bien no existe o bien el usuario no tiene acceso a ella o bien no hemos escrito la inyección correcta SQL para el motor de base de datos que se está utilizando (Hemos de recordad que SQL a pesar de ser un “estándar” no tiene las mismas implementaciones en los mismos motores de bases de datos). Otro posible motivo de fallo puede ser simplemente que el programado tenga el parámetro entre paréntesis y haya que jugar con las inyecciones por ejemplo, supongamos que hay un parámetro detrás del valor de id en la consulta que realiza la aplicación. En ese caso habría que inyectar algo como:

Id= 1) and (exists (select * from usuarios)

Supongamos que deseamos sacar el nombre del usuario administrador de una base de datos MySQL:

Id= 1 and 300>ASCII(substring(user(),1,1))

Con esa inyección obtendremos si el valor ASCII de la primera letra del nombre del usuario será menor que 300 y por tanto podemos decir que esa es un ISQL0. Lógicamente deberemos obtener el valor cierto recibiendo la noticia de Raúl. Luego iríamos acotando el valor ASCII con una búsqueda dicotómica en función de si las inyecciones son ISQL0 o ISQL+.

Id= 1 and 100>ASCII(substring(user(),1,1)) -> ISQL+ -> Falso
Id= 1 and 120>ASCII(substring(user(),1,1)) -> ISQL0 ->Verdadero
Id= 1 and 110>ASCII(substring(user(),1,1)) -> ISQL+ ->Falso
Id= 1 and 115>ASCII(substring(user(),1,1)) -> ISQL0 ->Verdadero
Id= 1 and 114>ASCII(substring(user(),1,1)) -> ISQL+ ->Falso


Luego podríamos decir que el valor del primer character ASCII del nombre del usuario es el 114. Un ojo a la tabla ASCII y obtenemos la letra ‘r’, probablemente de root, pero para eso deberíamos sacar el segundo valor, así que inyectamos el siguiente valor:

Id= 1 and 300>ASCII(substring(user(),2,1)) -> ISQL0 -> Verdadero

Y vuelta a realizar la búsqueda dicotómica. ¿Hasta que longitud? Pues averigüémoslo inyectando:

Id= 1 and 10> length(user()) ¿ISQL0 o ISQL+?

Todas estas inyecciones, como se ha dicho en un parrafo anterior deben ajustarse a la consulta de la aplicación, tal vez sean necesiaros paréntesis, comillas si los valores son alfanuméricos, secuencias de escape si hay filtrado de comillas, o caracteres terminales de inicio de comentarios para invalidad partes finales de la consulta que lanza el programador.

************************* Fin de la primera parte *******************************

3 comentarios:

mario dijo...

Tremendo articulo a eso llamo yo tener contentos a los lectores.
El que se entera pues muy bien como introducción, el que no se entera un poco de ciencia ficción muy digerible para como suelen ser estos textos, el que se entera a medias es como el que busca explicación física a los fenómenos de star wars.
PD: ¿El ejemplo es verídico y puedo pasar un rato divertido en el marca o el As (hablando así de Raúl será un sitio madridista)?jeje
PD2:Los navegadores te pillan automáticamente el RSS de blogspot en vez del de feedburner que pones en el lateral, no se como andarán las plantillas de blogger si permiten definir el automático o si es como prefieres que este, yo nunca le he buscado la lógica a lo que buscan los navegadores, me cargo los que vienen por defecto y los sustituyo en todos los sitios por el que quiera.xD

Maligno dijo...

Hola mario, el ejemplo no es verídico, pero en este blog tienes muuuuuchos otros ejemplos sobre lo mismo que sí son verídicos, (lee el post de el que no sabe es como el que no ve)

Yo el de Google no puedo contabilizarlo, así que no se cuantos lo leeis por él. Si os ponéis el de feedburner (la url completa) me entero, pero ... a tu gusto!

gracias por el comentario!

pultribe dijo...

No he podido evitar pensar en Chema cuando he visto esto
http://www.somethingofthatilk.com/index.php?id=271

Entradas populares