Por desgracia (o por suerte), muchos
de nosotros estamos acostumbrado a encontrarnos esas Inyecciones SQL tan
de libro como poner un ' AND '1'='1 y a partir de ahí empezar a jugar.
Desde luego, son las más rápidas de encontrar y de explotar, pero del
mismo modo son las menos divertidas.
Sin embargo, a veces me
encuentro con vulnerabilidades más curiosas y divertidas, por ejemplo es
muy típico eso de que la misma variable se use para varias cosas dentro
de un mismo código, y que para llegar a explotar la vulnerabilidad
tengas primero que conseguir que la cadena que metas no provoque errores
anteriores.
El caso que os voy a comentar
aquí es de este tipo, y está basado en casos reales que me he encontrado
por ahí. Imaginad una URL del siguiente tipo:
http://demo.pentester.es/buscar.aspx?ID=666999
La web simplemente muestra la descripción de un articulo concreto, hasta aquí nada "divertido".
Podemos
empezar a meter caracteres varios como si no hubiera mañana, a ver como
responde, comillas simples, dobles, cadenas típicas de inyección, etc,
hasta que introduzcamos algo como:
ID=666999' ERROR
Y nos devuelve un error como el siguiente:
Tiene toda la pinta de ser vulnerable a XPath Injection. Vamos a comprobarlo:
ID=666999' and 'foo'='foo
Wooops! Qué tenemos aquí? Parece
que además de usar el valor del parametro ID para la consulta XPath, a
posteriori usa ese mismo valor para realizar una petición SQL a una base
de datos Oracle.
¿Hará esta petición siempre? ¿O únicamente si la petición XPath devuelve resultados?
Forcemos que no devuelva ninguno, a ver que pasa:
ID=666999' and 'foo'='fuu
Con esto hemos conseguido que la
petición XPath sea siempre falsa, y efectivamente no nos devuelve
ningún error SQL (y la ficha aparece vacía de datos, evidentemente), así
que necesitamos que se nos devuelva algún valor y que la sintaxis sea
correcta para que podamos intentar la Inyección SQL.
El problema con el que nos
encontramos es que el contenido del parámetro ID es empleado en la
consulta SQL como un numerico, así que al poner las comillas para hacer
el XPath Injection fastidiamos la sintaxis de la sentencia SQL, y si no
ponemos la comilla entonces estamos haciendo que la consulta XPath no
devuelva ningún resultado, con lo que nunca se ejecuta la SQL.
¿Cómo salimos de esta?
Vamos a tener que inventarnos algún tipo de cadena de inyección que cumpla las siguientes condiciones:
- No provoque un error de sintaxis XPath
- Haga que devuelva algún valor en la consulta XPath
- No provoque un error de sintaxis SQL
Por suerte tenemos a la
vista tanto la sentencia XPath como la sentencia SQL, así que la cosa
nos va a resultar mucho más fácil. Seguro que existen mucha manera de
resolver este mismo problema, pero a mi la que primero me ha venido la
cabeza es la siguiente:
Dado que el principal problema
es que no podemos introducir instrucciones SQL por dentro de las
comillas simples (que es donde nos hace falta) porque eso provoca que la
petición XPath no devuelva ningún resultado y por tanto que la SQL
nunca se ejecute, una posible solución sería replicar la condición de la siguiente forma:
ID=666999' or ID=666999
Lo cual, al inyectarse dentro de la petición XPath, la dejará de la siguiente manera:
TEST/REGISTROS['ID=666999' or ID='666999']
Ahora podemos introducir todo lo
que queramos antes de la primera comilla (salvo comillas, claro está), y
eso no provocará ningún tipo de error XPath ni impedirá que la
sentencia devuelva los valores esperados, con lo que ya podemos
centrarnos en la SQL.
Si observamos la SQL, tiene un
montón de lineas, paréntesis, subqueries y demás. El valor que nosotros
introducimos, además, aparece en varios sitios de la query, pero por
suerte la primera vez que aparece es en una de las primeras condiciones
de los WHERE, así que nos va a resultar bastante sencillo "cargarnos" el
resto de la query comentándola:
ID=666999 -- ' or ID='666999
Eso dejaría una query SQL del aspecto de la siguiente:
SELECT a,b,c,d,e,f,g FROM t1,t2,t3,t4,t5,t6,t7,t8 WHERE id=666999 -- ' or ID='666999 [...]
Nota: Ponemos [...] en lugar de todo el churro que ya no nos interesa de ahora en adelante.
Como podeis ver, la cosa parece que se nos pone cuesta abajo a partir de este punto.
Ahora
solo tenemos que concatenarle un UNION con el número de columnas
adecuado a ver si conseguimos sacar información por pantalla:
ID=666999 UNION SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL FROM DUAL -- ' or ID='666999
Esto debería sacarnos la información del artículo con todo campos vacíos, pero en lugar de eso vemos lo siguiente:
Parece ser que el mismo
parámetro se usa una segunda vez para formar otra sentencia SQL, pero
esta ya no tiene 7 columnas, sino una sola, así que el UNION que nos va a
funcionar con una nunca funcionará con la otra. Esto podría ser un
problema, pero no nos pongamos nervioso, quizá simplemente dándole a
aceptar...
Efectivamente, aunque la segunda
sentencia nos devuelva un error, la primera se ejecuta y además imprime
los resultados por pantalla, lo cual podemos comprobarlo por ejemplo
mostrando el nombre del usuario:
ID=666999 UNION SELECT NULL,USER,SYS.DATABASE_NAME,NULL,NULL,NULL,NULL FROM DUAL -- ' or ID='666999
A partir de aquí, ya seguiríamos
el proceso de Inyección SQL habitual, intentar sacar las tablas,
información sensible, intentar escalar privilegios, e incluso ejecutar
código en el sistema operativo, si fuera posible.
FUENTE:
http://www.pentester.es/2012/01/xpath-y-sql-injection-todos-una.html
No hay comentarios:
Publicar un comentario