Inyección SQL Parte 1

En esta entrada vamos a hacer una introducción de inyección SQL y vamos a estar resolviendo algunos ejemplos prácticos de la página de PortSwigger.

Qué es SQLi?

Se trata de una vulnerabilidad web que permitiría manipular las peticiones legítimas por parte del sitio web con la finalidad de inyectar código SQL para alterar el comportamiento del aplicativo.
Para entender mejor el concepto os pongo un ejemplo práctico.
Imaginaos una página web con una gran cantidad de productos, estos están ordenados por categorías.
La página web vulnerable tiene una funcionalidad que permite buscar productos por categorías, dependiendo de la categoría que queramos visualizar, le indicaremos una u otra categoría. Por detrás lo que estará haciendo, es hacer una consulta SQL a la base de datos filtrando por todos los productos de la categoría indicada y mostrando los resultados en la web.
Ese buscador es vulnerable y permite al usuario manipular el comportamiento del aplicativo.
El usuario sería capaz de inyectar instrucciones SQL pudiendo extraer no solo los productos sino también información no autorizada de la base de datos, como por ejemplo usuarios y contraseñas.
Sería posible explotar esta vulnerabilidad debido a que no hay ninguna medida de seguridad que restrinja los tipos de datos introducidos por el usuario.
Por tanto, la vulnerabilidad reside en que no se filtra la entrada del usuario y esta pasa sin ninguna seguridad directamente a la consulta de la base de datos.

Qué es PortSwigger?

PortSwigger es una página web dónde encontramos recursos gratuitos para aprender y practicar las distintas vulnerabilidades existentes en el campo web. PortSwigger es la empresa desarrolladora de Burp Suite, herramienta muy utilizada para interceptar, modificar y enviar peticiones web entre otras muchas funciones. Veamos algunos ejemplos prácticos de Inyección SQL.

SQL injection vulnerability allowing login bypass

Vamos a empezar por algo sencillito. En este laboratorio nos encontramos una vulnerabildad SQLi en la función del login. El objetivo de este reto es acceder a la cuenta del usuario administrator.

Este es el login. Lo primero que podemos probar es ver si maneja bien el tema de las comillas, caracter muy importante en sentencias SQL. Así que, lo primero que haremos es introducir una comilla simple en el campo del usuario.

Al introducir la comilla simple en el campo de usuario, nos devuelve un error en la petición. Esto es buena señal, ya que nos indica que la comilla simple está alterando el comportamiento de la función del login y en consecuencia genera un error.

Esto es debido porque al introducir los datos del usuario y contraseña estos son enviados a una instrucción SQL parecida a la siguiente:

SELECT * FROM users WHERE username = 'usuario' AND password = 'contraseña'

Por lo tanto, al introducir una comilla simple en el campo usuario, lo que estamos generando es un error en el lenguaje SQL, sería algo así:

SELECT * FROM users WHERE username = ''' AND password = 'contraseña'

Habiendo visto que podemos manipular la consulta SQL, podemos abusar de ello introduciendo el usuario administrator seguido de dos guiones indicando que lo que vaya detrás de los guiones será un comentario y por tanto no se ejecutará en la consulta. Querdaría asi:

SELECT * FROM users WHERE username = 'administrator'--' AND password = 'loquesea'

No importa lo que introduzcamos en el campo Password ya que esa parte quedará comentada y no se ejecutará.

Como hemos previsto hemos conseguido acceder a la cuenta del administrador sin proporcionar contraseña.

SQL injection UNION attack, determining the number of columns returned by the query

En el caso anterior era un login en el que te permitía acceder o no. Ahora vamos a ver unos ejemplos en los que será posible extraer información de la base de datos.
En estos ejemplos la aplicación es vulnerable a SQLi y además el resultado de la consulta lo muestra en pantalla. Haremos uso de la instrucción UNION, que permite ejecutar una o más consultas SELECT a la vez.
Para que la consulta UNION funcione se deben cumplir dos requerimientos:
· Cada consulta individual debe devolver el mismo número de columnas.
· Cada consulta individual debe soportar el mismo tipo de dato en cada columna.

En este laboratorio el objetivo es determinar cuantas columnas devuelve la consulta SQL. El campo category filtra por categoría y es vulnerable a SQLi. Además muestra por pantalla el contenido de la consulta, algo que nos será de gran ayuda para ver si procedemos adecuadamente.

Ahí vemos un listado de productos y unas categorías para filtrar. Si pulsamos en cualquiera de ellas, nos filtrará los productos de dicha categoría y es en esa función donde está la vulnerabilidad.

URL: https://ac031f011edd0540c0ee5cef00b3007d.web-security-academy.net/filter?category=Tech+gifts

Podemos ver que la url termina con una variable category indicando la categoría a seleccionar. En este ejemplo podemos inyectar datos en la misma url, por lo que no haremos uso de Burp Suite. Si en la url quitamos Tech+gifts y añadimos una comilla simple, provocaremos un error SQL.

URL: https://ac031f011edd0540c0ee5cef00b3007d.web-security-academy.net/filter?category='

Ahora vamos a ver como encontrar el número de columnas que devuelve la consulta. Para ello haremos uso de la instrucción ORDER BY. Esta lo que hace es ordenar el output que mostrará en pantalla en base a la columna indicada. Por ejemplo, si en una consulta cualquiera le indicamos “ORDER BY 2”, ordenará el output basandose en la columna dos que será ascendente por defecto.
Si a una consulta que devuelve 3 columnas le indicas que la quieres ordenar por la 4 te dará un error SQL, sencillamente porque no existe una cuarta columna. Así que, la idea es ir enumerando hasta encontrarnos con la columna no existente.

URL: https://ac031f011edd0540c0ee5cef00b3007d.web-security-academy.net/filter?category=' ORDER BY 1-- 

Le indicamos la comilla simple al principio para cerrar la anterior comilla existente en la consulta e inyectamos nuestro código ORDER BY 1–. Recordad, finalizamos con los dos guiones para comentar el resto de la consulta. En principio la página no nos da ningún error, quiere decir que estamos inyectando código correctamente y que la columna 1 existe. Si probamos de ordenar por la 2 y la 3, vemos que tampoco nos da ningún error, por lo que deducimos que la consulta devuelve al menos tres columnas.

URL: https://ac031f011edd0540c0ee5cef00b3007d.web-security-academy.net/filter?category=' ORDER BY 4--

Cuando queremos ordenar por la cuarta columna es cuando provocamos el error. Perfecto! Es lo que buscábamos. Este error nos confirma que la consulta SQL devuelve tres columnas. Para completar el laboratorio debemos hacer uso de la instrucción UNION previamente explicada y hacer un select de 3 valores null. Al hacer un select de null, lo que le indicamos es que no nos muestre nada, pero aún así debemos indicarle los nulls exactos en relación con las columnas, es decir 3. Usamos null porque no sabemos que tipo de dato es soportado por cada columna. Si la columna uno devuelve un valor númerico e intentamos que nos muestre texto, estaremos provocando un error SQL. Por lo tanto el primer paso para ver que está todo correcto es seleccionar los tres null. Quedaría así:

URL: https://ac031f011edd0540c0ee5cef00b3007d.web-security-academy.net/filter?category=' UNION SELECT null,null,null--

SQL injection UNION attack, finding a column containing text

El siguiente laboratorio es parecido al anterior, estaremos resolviendo de la misma manera hasta el último punto donde cambiaremos los null por una cadena de texto para determinar que columna nos puede mostrar texto. Esto será vital para futuros ejemplos en los que tendremos que extraer información de la base de datos y para ello tendremos que saber que columna soporta texto.

Como vemos, el objetivo de este laboratorio es mostrar por pantalla la cadena ‘pJmqdR’. Vamos allá.
Primer paso, determinar el número de columnas que tiene la consulta.
Llegamos a ordenar hasta la 3 sin generar ningún error.

URL: https://acfb1fb11fff552ec0b12df400060049.web-security-academy.net/filter?category=' ORDER BY 3--

Es cuando queremos ordenar por la cuarta columna que nos genera el error, es decir devuelve tres columnas. Vamos a comprobarlo haciendo el UNION con los nulls.

URL: https://acfb1fb11fff552ec0b12df400060049.web-security-academy.net/filter?category=' UNION SELECT NULL,NULL,NULL--

Bien, no nos muestra ningún error. Para comprobar si algún campo admite texto, podemos indicarle entre comillas cualquier cadena en lugar de null. Para ello, iremos probando de uno en uno.

URL: https://acfb1fb11fff552ec0b12df400060049.web-security-academy.net/filter?category=' UNION SELECT NULL,'prueba',NULL--

Comprobando uno por uno, vemos que únicamente la columna dos acepta texto. Entre comillas simple le indicamos la cadena de texto que queremos que nos imprima por pantalla y vemos que por debajo de las categorías tenemos la palabra prueba mostrada. Para finalizar el laboratorio, en vez de la palabra prueba debemos hacer que muestre: pJmqdR

URL: https://acfb1fb11fff552ec0b12df400060049.web-security-academy.net/filter?category=' UNION SELECT NULL,'pJmqdR',NULL--

SQL injection UNION attack, retrieving data from other tables

Vamos a resolver un último laboratorio para esta entrada. La vulnerabilidad es la misma que en los anteriores laboratorios, pero en este caso tenemos que extraer todos los usuarios y contraseñas de la tabla users.
Volvemos a la misma metodología, primer paso encontrar el número de columnas exactas. En este caso, son dos columnas.

Segundo paso, averiguar que columnas soportan texto.

Perfecto, ambas columnas soportan texto. Podremos sacar usuarios en una y contraseñas en otra.
La consulta para extraer dicha información de la base de datos sería así:

SELECT username,password FROM users

Vamos a inyectar nuestra consulta para que nos muestre las credenciales.

https://acdb1f1e1f55dfa2c0a25cf4001b0093.web-security-academy.net/filter?category=' UNION SELECT username,password FROM users--

Perfecto! Nos ha devuelto tres usuarios con sus respectivas contraseñas. Para finalizar el laboratorio tenemos que acceder a la cuenta del administrador con la contraseña mostrada y listo!

En este caso, nos han proporcionado el nombre de las columnas y el nombre de la tabla, en la próxima entrada veremos como sacar los nombres de cualquier columna o tabla. Además también veremos blind SQL, cuando el aplicativo no muestra información por pantalla todavía hay técnicas que podemos usar para extraer datos.

Un saludo y hasta la próxima!

Óscar Montoya