Contenidos
Uno de los mayores problemas al enseñar SQL Injection es que muchas veces se explica solo en teoría.
Pero cuando el alumnado ve:
- la tabla
- los datos
- la consulta vulnerable
- y el resultado real
…es cuando realmente entiende el problema.
Por eso un pequeño laboratorio con Docker y MySQL funciona tan bien en clase.
1️⃣ Crear una base de datos vulnerable
DROP DATABASE IF EXISTS demo_inyeccion_salarios;
CREATE DATABASE demo_inyeccion_salarios;
USE demo_inyeccion_salarios;
2️⃣ Crear tabla de empleados
CREATE TABLE empleados (
id INT AUTO_INCREMENT PRIMARY KEY,
usuario VARCHAR(50),
password VARCHAR(50),
puesto VARCHAR(50),
salario INT
);
Insertamos algunos usuarios:
INSERT INTO empleados(usuario,password,puesto,salario) VALUES
('ana','1234','Analista',32000),
('carlos','abcd','Administrador Sistemas',38000),
('marta','pass','Marketing',42000),
('director','supersecret','Director General',150000);
3️⃣ Consulta normal
Login correcto:
SELECT usuario, puesto, salario
FROM empleados
WHERE usuario='ana'
AND password='1234';
Resultado esperado:
| usuario | puesto | salario |
|---|---|---|
| ana | Analista | 32000 |
4️⃣ Login incorrecto
SELECT usuario, puesto, salario
FROM empleados
WHERE usuario='ana'
AND password='xxxx';
Resultado:
Empty set
Hasta aquí todo parece normal.
5️⃣ Inyección SQL clásica
Ahora llega lo interesante.
SELECT usuario, puesto, salario
FROM empleados
WHERE usuario='' OR '1'='1';
La condición:
'1'='1'
siempre es verdadera.
Resultado:
| usuario | puesto | salario |
| ana | Analista | 32000 |
| carlos | Administrador Sistemas | 38000 |
| marta | Marketing | 42000 |
| director | Director General | 150000 |
Y aquí es cuando muchos entienden por primera vez por qué concatenar cadenas en SQL es peligrosísimo.
🔥 Inyección SQL con UNION
Otro ejemplo muy visual consiste en mostrar cómo una consulta pública puede terminar filtrando información privada.
6️⃣ Tabla pública
CREATE TABLE empleados_publicos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(50),
departamento VARCHAR(50),
email VARCHAR(100)
);
7️⃣ Tabla secreta
CREATE TABLE salarios_secretos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(50),
puesto VARCHAR(50),
salario INT
);
8️⃣ Consulta legítima
SELECT nombre, departamento, email
FROM empleados_publicos
WHERE nombre='Ana';
La aplicación solo debería mostrar datos públicos.
9️⃣ Ataque con UNION
SELECT nombre, departamento, email
FROM empleados_publicos
WHERE nombre=''
UNION
SELECT nombre,puesto,salario FROM salarios_secretos;
Ahora la consulta mezcla:
- datos públicos
- y datos privados
Resultado:
| nombre | puesto/departamento | salario/email |
| Ana | Analista | 32000 |
| Carlos | Administrador Sistemas | 38000 |
| Marta | Responsable Marketing | 42000 |
| Luis | Director General | 150000 |

