Saltar al contenido
Open Security
Ciberseguridad PrácticaIntermedio· 35 min

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.

#sql#owasp#defensivo

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-check
  • lab-check revisa 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-parametrizada corre el mismo chequeo y copia tu evidencia a evidencia/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.

¿Hiciste el lab?

Si querés, guardá lo que hiciste (comandos, notas, un repo) para volver después. Y si encontrás un error o querés mejorar este lab,contribuí al repo. El progreso se guarda solo en tu navegador.