SQL injection defensiva: queries parametrizadas
Un lab seguro para entender por qué concatenar input en SQL rompe el límite entre datos y código, y cómo lo corrigen las consultas parametrizadas.
Antes de empezar necesitás
- Entender formularios o APIs simples
- Idea básica de SQL SELECT/WHERE
Al terminar vas a poder
- Distinguir datos de código SQL
- Reconocer concatenación peligrosa
- Diseñar queries parametrizadas
- Documentar el bug desde la defensa
Entorno listo con Podman
Una base SQLite de juguete con un buscador vulnerable y otro para que lo pases a query parametrizada. lab-check prueba tu versión con un email normal y con el input de juguete.
# Una vez: cloná el repo y construí la imagen
git clone https://github.com/ValentinTorassa/Open-Security-Labs.git
cd Open-Security-Labs
podman build -t osl/sql-injection-parametrizada -f entornos/ciberseguridad/sql-injection-parametrizada/Containerfile entornos
# Abrí el entorno (se borra al salir)
podman run --rm -it --name osl-sql-injection-parametrizada --hostname labs osl/sql-injection-parametrizada
# Al terminar, adentro del contenedor
lab-checklab-checkrevisa lo que hiciste y guarda el resultado en/home/vt/evidencia. Desde otra terminal, en la carpeta del repo,npm run lab:check -- ciberseguridad/sql-injection-parametrizadacorre el mismo chequeo y copia tu evidencia aevidencia/sql-injection-parametrizada/.- ¿Usás Docker? Cambiá podman por docker en los comandos y funciona igual.
- Qué trae, qué revisa y sus límites: entornos/ciberseguridad/sql-injection-parametrizada/README.md.
SQL injection ocurre cuando input no confiable deja de ser dato y pasa a formar parte del programa SQL. La defensa no es “filtrar palabras raras”: es mantener separados código y datos.
El patrón vulnerable
email = request.query.email
sql = "SELECT id, email FROM users WHERE email = '" + email + "'"
db.query(sql)
El problema es que email termina dentro del texto SQL. Si el usuario controla ese valor, controla parte de la query.
La versión segura
email = request.query.email
sql = "SELECT id, email FROM users WHERE email = ?"
db.query(sql, [email])
El ? no se reemplaza concatenando strings. El driver manda el valor como parámetro.
Cómo documentarlo
source: request.query.email
sink malo: string SQL concatenado
impacto: el input puede cambiar la lógica de la consulta
mitigación: parámetro del driver + validación de formato
test bueno: email normal devuelve un usuario
test malo: input raro no cambia la estructura de la query
Lo que practicás en este lab
Llevátelo a tu repo si querés, pero no es obligatorio: es tu aprendizaje.
- Pseudocódigo vulnerable y corregido
- Tabla source → sink → impacto → mitigación
- Writeup con tests de input normal e input malicioso de juguete
Reto
Tomá una búsqueda de usuarios por email. Escribí la versión vulnerable por concatenación y la versión segura con parámetro. Explicá qué parte deja de interpretarse como SQL.
Resolvelo y escribí dos líneas explicando qué pasó. Con eso lo fijás.