Oracle Blind SQL Injection en Order By

 Hoy quería comentar un caso curioso que me he encontrado recientemente durante un pentest de una aplicación web. La aplicación en cuestión es muy grande, con muchísimos menús, submenús, cantidad de roles, checkboxes y dropdown menus que muestran diferentes páginas en función de los valores que tengan… Vamos, una cosa incómoda de manejar y con muchos campos donde intentar inyectar basurilla. Y además, no está permitido el uso de herramientas automáticas (requisitos del cliente).

Lo más habitual suele ser que una web sea vulnerable a SQL injection en todos los campos del mismo tipo, o del mismo formulario, existiendo siempre la posibilidad de que un cambio de desarrollador o un parche a posteriori deje un agujero que no estaba previamente. La aplicación de la que os hablo hoy es de este tipo, una aplicación antigua que ha pasado por las manos de varios desarrolladores y sobre la que se han aplicado parches y añadido nuevas funcionalidades con el paso del tiempo. Pues allá que iba yo auditando la susodicha, llevando recorrido ya más de un 75% de la web sin haber sido capaz de encontrar ningún SQLi. Y fue en aquel preciso momento, desvanecida ya toda esperanza, cuando Isildur, Hijo del Rey recurrió a la espada de su padre… cuando me topé con la típica tabla que se puede ordenar clickando en los encabezados de las columnas. Algo muy parecido a esto:

Tabla

Tabla ordenable

Si echamos un vistazo a lo que sucede cuando hacemos click en “1 Year”, lo que nos mostrará Burp nos parecerá bastante sospechoso, y será muy parecido a lo siguiente:

Parámetros en Burp

Llegados a este punto, no queda más remedio que intentar una inyección en esos parámetros, a pesar de que existían otras tablas de la aplicación con aspecto idéntico, e idénticos nombres de parámetros que no eran inyectables. Para llevar a cabo esta tarea hay que tener en cuenta un par de peculiaridades sobre las inyecciones en cláusulas Order By, y en Oracle. A saber:

  • No es necesario el uso de comillas: En la cláusula Order By se colocan directamente los nombres de las columnas de la tabla sin necesidad de comillas, por lo que no hará falta para la inyección cerrar comillas previamente abiertas.
  • No está permitido el uso de UNION: SQL no permite el uso de UNION en la cláusula Order By (tampoco tendría mucho sentido), por lo que no podremos usar ésta técnica para extraer información.
  • Oracle no permite SELECT sin su correspondiente FROM, por lo que para seleccionar consultas se ha de utilizar la tabla dummy llamada dual.
  • Lo mismo da ordenar por una columna por nombre (ORDER BY Year) que por posición (ORDER BY 1).

Esto provoca que muchos programadores piensen que no es posible inyectar en cláusulas ORDER BY, y descuidan la debida validación de la entrada de usuario para estos casos. Como siempre, lo primero que a uno se le ocurre es meter unas comillas, y ver si la aplicación responde con un error maravilloso denotando que es vulnerable (y facilitando la posterior extracción de datos, ya que no podremos usar UNION). Por desgracia (para mí), las comillas simplemente devolvían la tabla ordenada de la misma forma que se muestra en la primera imagen, es decir, sin orden aparente. El mismo resultado se produce si en lugar de “Year”, utilizamos como valor “España” o “Manolito”. Hasta aquí podría parecer que no es vulnerable, y que quizá el JSP de la página haga un “switch” y cree la query a la base de datos sin los valores que estamos manipulando. En ese caso, sería posible que la rama default del switch hiciera la query sin ordenar, algo así:


switch (Sort_by){
case "Year":
query+="ORDER BY Year;";
break;
case "Month":
query+="ORDER BY Month;";
break;
default:
query+=";"
break;
}

Por suerte para nosotros, no es el caso. Lo era en ésta misma aplicación, en tablas anteriores, pero se les olvidó una; y con una basta. La pista la da que si en lugar de SortBy=”Year”, enviamos SortBy=1, la tabla se ordena como esperamos, por lo que o el switch cubre muchos casos, o aquí tenemos algo para jugar.

Si repasamos un poco nuestro escenario, tenemos una inyección ciega en un campo ORDER BY en Oracle. Al ser un caso de blind SQLi, no nos queda más remedio que tratar de construir algún tipo de lógica binaria para diferenciar aciertos de errores en las consultas. Probablemente, lo primero que os venga a la cabeza sea construir una consulta que ordene por la primera columna si el resultado es True, y por la segunda si es False. Como ejemplo, vamos a construir dicha query para obtener el primer caracter del usuario con el que corre la instancia de Oracle. Paso a paso:

Select user from dual -- Obtiene el usuario de la instancia de Oracle, utilizando la dummy table dual.

case WHEN (1=1) THEN 1 ELSE 2 END -- Devuelve 1 si (1=1) es True, y 2 en otro caso.

ascii(substr(user,1,1)) -- Devuelve el valor ascii del primer caracter de "user"

Sort_by=(SELECT case WHEN ascii(substr(user,1,1))=80 then 1 else 2 end from (SELECT user from dual)) -- Obtiene el usuario de la tabla dummy dual. De ese string, saca el primer caracter y lo convierte a ascii. Si ese valor es igual a 80, devuelve 1 (ordenando por la primera columna) y si no, devuelve 2 (ordenando por la segunda).

También se podría haber hecho la query de la siguiente forma (por si a alguien le es más fácil de ver):

(case WHEN ascii(substr(SELECT user FROM dual,1,1))=80 then 1 else 2 end)

Conseguido esto sólo queda iterar por los valores de la tabla ascii para conseguir el nombre completo del usuario, o usar la misma idea para obtener las tablas, bases de datos o contenido de las mismas.

Hay dos conclusiones que extraer de esta pequeña entrada. La primera, que a pesar de que parezca que no se va a encontrar un fallo en una aplicación, hay que seguir probando todos los campos hasta el final, porque puede haber sorpresas. La segunda, que las inyecciones en ORDER BY, no sólo son posibles, sino que son muy efectivas, porque habitualmente no están filtradas por los desarrolladores.

Cualquier cosa, me encantará un comentario.

Salud

Anuncios
Tagged with: , , ,
Publicado en web hacking
2 comments on “Oracle Blind SQL Injection en Order By
  1. miguel dice:

    gran entrada y mejores consejos!
    lo que no tiene ningún sentido es la limitación del uso de herramientas automáticas… otra de esas limitaciones SIN SENTIDO.

  2. Adrián dice:

    ¡Gracias miguel!

    Hay algunas restricciones que lo único que consiguen es que no hagas tu trabajo todo lo bien que podrías, pero bueno, el cliente manda. También te digo que las herramientas automáticas hay muchísimas cosas que se dejan fuera, y algunas son bastante obvias.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Archive
A %d blogueros les gusta esto: