Volver a la lista

Inyección SQL y consultas parametrizadas

Comprenda cómo funciona la inyección SQL y aprenda a evitarla por completo mediante consultas parametrizadas.

Intermedio
|
7min
|
Verificado (2026-07)
Progreso0/55 (0%)

Inyección SQL y consultas parametrizadas

Al finalizar este tema

Podrás explicar cómo funciona la inyección SQL y escribir código que la defienda mediante consultas parametrizadas.


¿Qué es la inyección SQL?

La inyección SQL es un ataque que inserta código SQL en las entradas del usuario para manipular la base de datos. Es uno de los ataques más antiguos, peligrosos y aún más comunes en la seguridad web.


Cómo funciona el ataque

Imagina un formulario de inicio de sesión. Cuando un usuario introduce su correo electrónico, el servidor lo procesa de la siguiente manera:

javascript
// ❌ Código peligroso — inserta la entrada directamente en SQL
const email = req.body.email;
const sql = `SELECT * FROM users WHERE email = '${email}'`;
connection.query(sql);

Entrada válida: hoon@example.com

sql
SELECT * FROM users WHERE email = 'hoon@example.com'
-- Funcionamiento normal

Entrada de ataque: ' OR '1'='1

sql
SELECT * FROM users WHERE email = '' OR '1'='1'
-- '1'='1' es siempre verdadero → ¡se devuelven todos los datos de usuario!

Un ataque más peligroso: '; DROP TABLE users; --

sql
SELECT * FROM users WHERE email = ''; DROP TABLE users; --'
-- El punto y coma termina la primera consulta y ejecuta el comando para eliminar la tabla
-- -- comenta el resto

Punto clave: El problema radica en que la entrada del usuario altera la estructura misma de la consulta SQL.


Defensa: Consultas parametrizadas

Las consultas parametrizadas (Parameterized Query, Prepared Statement) separan la estructura de la consulta SQL de los datos.

javascript
// ✅ Código seguro — usa marcadores de posición
const email = req.body.email;
connection.query(
  'SELECT * FROM users WHERE email = ?',
  [email]
);

Incluso si se recibe una entrada de ataque ' OR '1'='1:

sql
SELECT * FROM users WHERE email = '\' OR \'1\'=\'1'
-- Todo se trata como un único valor de cadena. La estructura SQL no cambia.

El motor de la base de datos analiza primero la estructura SQL y, a continuación, inserta de forma segura los valores en la posición ?. Independientemente de lo inusuales que sean los valores, no se interpretan como comandos SQL.


Patrones de parametrización por lenguaje

Node.js (mysql2)

javascript
// ? Marcador de posición
connection.query('SELECT * FROM users WHERE id = ?', [userId]);
connection.query(
  'INSERT INTO users (name, email) VALUES (?, ?)',
  [name, email]
);

Python (sqlite3 / psycopg2)

python
# ? Marcador de posición (sqlite3)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
# %s Marcador de posición (psycopg2 / MySQL Connector)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Java (JDBC)

java
PreparedStatement stmt = conn.prepareStatement(
    "SELECT * FROM users WHERE id = ?"
);
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();

La sintaxis puede variar, pero el principio es el mismo: separar el código SQL de los datos.


Capas de defensa adicionales

Aunque las consultas parametrizadas son fundamentales, existen capas de defensa adicionales:

MétodoFunción
Consultas parametrizadasDefensa principal: protege la estructura del código SQL
Validación de entradaFiltrado previo (formato de correo electrónico, rango numérico, etc.)
Principio de privilegio mínimoConceder solo los permisos necesarios a la cuenta de la base de datos (eliminar DELETE si no es necesario)
Uso de ORMHerramientas como Sequelize y Prisma aplican la parametrización internamente

Lo más importante: no concatenar directamente la entrada del usuario en una cadena de código SQL. Si se cumple esta única regla, no se producirán inyecciones SQL.


💬 Preguntas y comentarios

0 comentarios

Puedes publicar sin iniciar sesión. Los comentarios de invitados no pueden editarse ni eliminarse después.

0/2000

Cargando...