SQL Injection

¿Qué es y cómo funciona?

la inyección SQL es una técnica de inyección de código que se utiliza para atacar aplicaciones basadas en datos, en las que se insertan declaraciones SQL maliciosas en un campo de entrada para su ejecución (por ejemplo, para volcar el contenido de la base de datos al atacante).

Comandos básicos de SQL

Comando
Descripción

SELECT

Se utiliza para seleccionar las columnas que se desean mostrar en la consulta.

FROM

Se utiliza para especificar la tabla o tablas de las que se desean recuperar los datos.

WHERE

Se utiliza para establecer una condición que deben cumplir los datos que se desean recuperar.

GROUP BY

Se utiliza para agrupar los datos por una o varias columnas.

HAVING

Se utiliza para establecer una condición que deben cumplir los grupos que se desean recuperar.

ORDER BY

Se utiliza para ordenar los datos por una o varias columnas.

LIMIT

Se utiliza para limitar el número de filas que se desean recuperar.

OFFSET

Se utiliza para establecer el número de filas que se deben saltar antes de empezar a recuperar datos.

DISTINCT

Se utiliza para eliminar las filas duplicadas de los resultados de la consulta.

IN

Se utiliza para especificar una lista de valores que deben cumplir una condición.

BETWEEN

Se utiliza para especificar un rango de valores que deben cumplir una condición.

LIKE

Se utiliza para buscar valores que contengan una cadena de caracteres determinada.

IS NULL

Se utiliza para buscar valores que sean nulos.

IS NOT NULL

Se utiliza para buscar valores que no sean nulos.

La tabla que se presenta a continuación enumera las posibilidades de las vistas de metadatos del sistema en diferentes bases de datos comunes:

Base de datos
Vista de metadatos
Descripción

MySQL

information_schema.SCHEMATA

Contiene una fila por cada base de datos en el servidor MySQL.

MySQL

information_schema.TABLES

Contiene información sobre cada tabla en cada base de datos en el servidor MySQL.

MySQL

information_schema.COLUMNS

Contiene información sobre cada columna en cada tabla en cada base de datos en el servidor MySQL.

MySQL

information_schema.INDEXES

Contiene información sobre cada índice en cada tabla en cada base de datos en el servidor MySQL.

PostgreSQL

pg_catalog.pg_namespace

Contiene información sobre cada esquema en la base de datos de PostgreSQL.

PostgreSQL

pg_catalog.pg_tables

Contiene información sobre cada tabla en cada esquema en la base de datos de PostgreSQL.

PostgreSQL

pg_catalog.pg_columns

Contiene información sobre cada columna en cada tabla en cada esquema en la base de datos de PostgreSQL.

PostgreSQL

pg_catalog.pg_indexes

Contiene información sobre cada índice en cada tabla en cada esquema en la base de datos de PostgreSQL.

SQL Server

sys.schemas

Contiene información sobre cada esquema en la base de datos de SQL Server.

SQL Server

sys.tables

Contiene información sobre cada tabla en cada esquema en la base de datos de SQL Server.

SQL Server

sys.columns

Contiene información sobre cada columna en cada tabla en cada esquema en la base de datos de SQL Server.

SQL Server

sys.indexes

Contiene información sobre cada índice en cada tabla en cada esquema en la base de datos de SQL Server.

Check List

Tipos de SQL Injection

SQL In-Band

Tenemos que saber que esto:

Es lo mismo que esto:

Así que podemos hacer después del id=2 mas consultas basadas en error, una vez entendido esto, vamos a las comandos:

Test si hay sql injection

Error based - ORDER BY

Este proceso es para determinar cuantas columnas existen en la base de datos a la que estamos intentando de sacar información. Cuando hayamos hecho por ejemplo order by 10 -- - y no salga información solo hace falta ir bajando hasta que salga y así sabremos cuantas columnas tiene la bbdd.

Nota importante: El caso es que a veces puede pasar que no sale el error, lo que hay que hacer es lo de siempre order by 100-- - hasta que te salga información, cuando te salga información por ejemplo cuando has hecho order by 4-- - significa que hay 4 columnas. Y ya puedes seguir con la inyección.

Recordar que para que muestre la info tenemos que poner el primer parametro que sea erroneo porque sino no funcionará. Si existe el id=2 al hacer la query id=2 union select 1,2,3,database() -- - no saldrá información por que es correcto el id, habría que poner id=-1 o id=23123 para que funcione.

UNION

A veces puede pasar que filtramos por (username y password) y puede que no aparezcan las contraseñas, eso es por que a veces suele estar en la columna "authentication_string"

Así que deberíamos añadir el campo en la syntaxis

Test en buscador

A veces podemos sacar información en un buscador de la web mediante sqlinjection.

Test en Login

veces con este tipo de sql injectio podemos bypassear el login de un panel.

SQL Blind/Boolean-based

Cuando hablamos de una SQL Injection la cuál no podemos ver el resultado de la petición se le llama a ciegas, y dentro de esta misma variable hay de 2 tipos:

  • Basada en tiempo

  • Basada en condiciones

Tiempo

Una SQL Injection de tiempo son cuando enviamos una petición y le ponemos el parámetro sleep y dependiendo de lo que tarde en responder podriamos determinar si los datos son correctos o no.

Ejemplo de como sería por detrás

Ahora pondré un ejemplo de si la base de datos con la que estamos trabajando actualmente empieza por 'a' tarda 5 segundos en responder:

Primera petición

Segunda petición

Como podemos ver en la segunda petición no nos da ningún resultado, eso nos da a entender que el primer carácter de la base de datos empieza por j. Y en la primera obviamente sería el resultado de una petición no correcta ya que no empieza por a.

Este proceso es un poco tedioso a la hora de hacerlo manual, por eso os traigo un script en python que estuve haciendo en un curso de s4vitar el cuál te automatiza todo el proceso:

Solamente tenemos que cambiar 2 parámetros que cambian dependiendo de a lo que nos enfrentemos:

  • main_url

  • sql_url

SQL-URL Examples

Script python para SQL Injection en GET

Resultado del script

Script python para SQL Injection en POST

Condiciones

Una SQL Injection condicional es cuando enviamos la petición y le ponemos la condición true o false.

Si ponemos al final de la query esto ' OR 1=1-- - nos aparecera de nuevo toda la tabla ya que le estamos diciendo que obvie todo lo de atrás y que muestre todo ya que 1=1 es true.

O por ejemplo imaginemos que estamos enfrentandonos a una tabla de usuarios y queremos descubrir si el primer carácter empieza por a.

Cómo el primer usuario es jack, la condición te dice que es 0 que es false. Pero si le ponemos ='j' veremos que pone 1.

Otro ejemplo que lo estaré haciendo con curl es el siguiente:

El id 9 no existe pero como despues hacemos un OR 1=1 pues lo detecta como true que le decimos que obvie lo de atrás y muestre todo

Pero si ponemos 1=2 que es false nos dará un 404

Script de python para condicones

Ejemplo SQL Injection - Error Based

Este ejemplo lo he realizado con un laboratorio que puedes instalarte en docker, aquí el link

Primero tenemos que saber cuantas columnas tiene la base de datos actual, con BurpSuite interceptamos la petición y la mandamos al Repeater para hacer las pruebas.

Vemos que con 5 ya no nos da error

Empecemos con lo bueno, vamos a realizar unas pruebas para ver si poniendo con UNION unos datos se representa en la tabla

Aparece la base de datos actual sqlitraining

Ahora vamos a listar todas las bases de datos existentes del servidor

Vemos que se listan todas las bases de datos

En el siguiente comando listaremos las tablas de la base de datos sqlitraining

Podemos ver que hay 2 tablas, la products y la users

Seguidamente listaremos todas las columnas de la tabla users

Vemos los campos id, username, password, fname, description

Nos interesan los campos username y password

Si cambiamos la respuesta a Pretty podemos seleccionar todos los datos

También podemos ver estos datos de una manera más ordenada poniendo el campo username y password en las columnas

SQL Map

Sintaxis principal

Sqlmap en buscador

Cuando hayamos conseguido el payload del sql map para inyectarlo manualmente, al final poner siempre %23.

Sqlmap en Login

Sqlmap -r

Primero hay que interceptar la petición y después guardarla en un fichero y entonces decirle al sqlmap que parámetro tiene que consultar

El parámetro al que queremos que compruebe si es vulnerable es `searchitem=test`

En /usr/share/sqlmap/output/<target> encontramos todos los logs de los comandos y info que hemos hecho. Si no hay nada ejecuta la siguiente comanda: sqlmap -r <URL file> -p user --technique=B --banner -v3 --flush-session

SQL Map cheat sheet

Aquí encontrarás todos los comandos de sqlmap: Cheat sheet

Last updated