CodeGym /Cursos /SQL SELF /Protección contra inyecciones SQL y otros ataques: PREPAR...

Protección contra inyecciones SQL y otros ataques: PREPARE, EXECUTE, parameterized queries

SQL SELF
Nivel 48, Lección 3
Disponible

Bueno, primero vamos a ver qué estamos protegiendo, o mejor dicho, de quién. Al principio de este nivel ya mencionamos las inyecciones SQL, uno de los ataques más populares y destructivos contra bases de datos. El ataque funciona así: el atacante manda código SQL malicioso en tu consulta para "engañarla" y obtener acceso a datos a los que no debería acceder. Ahora vamos a ver esto con más detalle.

Ejemplo de inyección SQL

Supón que tienes una aplicación web con un simple input de nombre de usuario y contraseña. El backend ejecuta una consulta SQL para comprobar si el usuario existe en la base de datos:

SELECT * FROM users WHERE username = 'admin' AND password = 'password123';

Esta consulta se ve perfecta... mientras el usuario mete datos correctos. Pero ¿qué pasa si alguien mete esto?

  • Nombre de usuario: admin' --
  • Contraseña: (dejamos este campo vacío)

Al final la consulta se convierte en algo así:

SELECT * FROM users WHERE username = 'admin' -- AND password = 'password123';

Fíjate en los caracteres --, que en SQL marcan el inicio de un comentario. Todo lo que va después se ignora. Como resultado, la comprobación de la contraseña se salta y el atacante entra como administrador.

Consecuencias potenciales de las inyecciones SQL

Una inyección SQL puede tener consecuencias horribles:

  1. Obtener acceso no autorizado a los datos. Por ejemplo, el atacante puede ver datos confidenciales como contraseñas de usuarios.
  2. Eliminar o modificar datos. Alguien puede borrar toda una tabla o liarla parda.
  3. Ejecutar código SQL arbitrario. Imagina que el atacante lanza el comando DROP DATABASE... Sí, suena a pesadilla.

¡Pero no somos de los que se asustan fácil! PostgreSQL nos da un montón de herramientas para protegernos de estos ataques.

¿Cómo protegerse? Métodos para prevenir inyecciones SQL

  1. Uso de consultas preparadas (PREPARE y EXECUTE)

Las consultas preparadas (prepared statements) son como una receta probada para tu código SQL. Funcionan así: "preparas" la consulta SQL una vez y luego le pasas los datos aparte. Así es imposible meter código malicioso.

Aquí tienes un ejemplo de cómo hacerlo bien:

Prepara la consulta usando PREPARE.

PREPARE user_login (text, text) AS
SELECT * 
FROM users 
WHERE username = $1 AND password = $2;

La consulta con dos parámetros $1 y $2 espera que los valores reales se pasen después.

Usa EXECUTE para ejecutar la consulta.

EXECUTE user_login('admin', 'password123');

En este caso, PostgreSQL escapa automáticamente todos los datos del usuario, evitando la inyección de código SQL malicioso.

Ventajas de este enfoque:

  • No se puede hacer una inyección SQL, porque los parámetros se tratan como datos normales, no como parte del código SQL.
  • Las consultas son más seguras y se ejecutan más rápido gracias al caché del plan de ejecución.
  1. Consultas parametrizadas (Parameterized Queries)

Este método es especialmente popular en apps hechas en lenguajes como Python o Java. En vez de trabajar a mano con PREPARE y EXECUTE, puedes usar librerías o un ORM que gestionan los parámetros automáticamente.

Ejemplo con Python y la librería psycopg2:

import psycopg2

connection = psycopg2.connect(
    dbname="tu_db",
    user="tu_usuario",
    password="tu_contraseña",
    host="localhost",
    port="5432"
)

cursor = connection.cursor()

# Uso de una consulta parametrizada
username = "admin"
password = "password123"
query = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(query, (username, password))

# ¡Tus datos están totalmente seguros!
result = cursor.fetchall()
print(result)

Fíjate en el %s en la consulta SQL — ahí es donde se mete el parámetro. La librería psycopg2 se encarga de pasar los datos de forma segura.

  1. Validación de los datos de entrada

Si vas a pasar datos que mete el usuario, asegúrate de que cumplen lo que esperas. Por ejemplo:

  • Para datos de texto, usa expresiones regulares para comprobar que no tienen caracteres prohibidos.
  • Para datos numéricos, asegúrate de que realmente son números.

Ejemplo en Python:

import re

username = input("Introduce el nombre de usuario: ")

# Permitimos solo letras, números y guiones bajos
if re.match(r"^\w+$", username):
    print("Nombre de usuario correcto")
else:
    print("¡Nombre de usuario peligroso!")
  1. Uso de privilegios mínimos

Asegúrate de que los roles que usas para ejecutar consultas tengan solo los privilegios mínimos necesarios. Por ejemplo, no des acceso a DROP TABLE o ALTER TABLE si no hace falta.

  1. Registro de acciones sospechosas

Puedes usar parámetros de PostgreSQL para monitorizar la actividad de los usuarios:

  • log_statement = 'all' — registra todas las consultas.
  • log_connections = on — registra todas las conexiones a la base de datos.

Estos parámetros ayudan a detectar acciones potencialmente peligrosas.

Ejemplos de implementación

Ejemplo 1: Uso de una consulta preparada en SQL

-- Creamos una consulta preparada
PREPARE check_credentials (text, text) AS
SELECT * FROM users WHERE username = $1 AND password = $2;

-- Ejecutamos la consulta con parámetros seguros
EXECUTE check_credentials('admin', 'password123');

Ejemplo 2: Consulta parametrizada en Python

query = "UPDATE users SET last_login = NOW() WHERE username = %s"
username = "admin"
cursor.execute(query, (username,))

Recomendaciones de seguridad

Valida siempre los datos de entrada. Nunca confíes en los datos que vienen del usuario.

Usa solo consultas preparadas o parametrizadas. Estos métodos son tu principal barrera contra las inyecciones SQL.

Asigna roles con los privilegios mínimos necesarios. Así minimizas el daño si un atacante consigue acceso.

Configura el registro y revisa los logs regularmente. Mantente al tanto de la actividad en tu base de datos.

Las inyecciones SQL son, claro, un bicho feo, pero usando consultas preparadas, parametrizadas y siguiendo buenas prácticas, vas a proteger tu base de datos y podrás dormir tranquilo por las noches, sin miedo a que alguien "accidentalmente" borre todas tus tablas. PostgreSQL te da todas las herramientas para esto, ¡así que dale caña!

2
Tarea
SQL SELF, nivel 48, lección 3
Bloqueada
Uso de una consulta preparada para verificar el login
Uso de una consulta preparada para verificar el login
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION