La inyección SQL existe desde hace décadas y todavía aparece en las evaluaciones de seguridad actuales, no porque sea una amenaza nueva y exótica, sino porque es notablemente fácil de introducir por accidente. Si eres un diseñador web principiante y construyes cualquier formulario, página de inicio de sesión o cuadro de búsqueda que toque una base de datos, entender la inyección SQL no es un conocimiento opcional: es un requisito básico para construir cualquier cosa que sea segura de poner en línea.

La inyección SQL ocurre cuando datos no confiables del usuario se insertan directamente en una consulta SQL, permitiendo que un atacante cambie lo que esa consulta realmente hace. En lugar de solo buscar un producto o iniciar sesión, un atacante puede usar la inyección SQL para leer datos privados, saltarse por completo un formulario de inicio de sesión o, en los peores casos, modificar o eliminar datos de la base de datos.

Esta guía explica qué es la inyección SQL, recorre un ejemplo sencillo de cómo funciona, por qué es tan peligrosa y, lo más importante, los pasos concretos que debes seguir para prevenirla en tus propios proyectos.

¿Qué Es la Inyección SQL?

La inyección SQL es una vulnerabilidad de seguridad web que permite a un atacante interferir con las consultas SQL que una aplicación envía a su base de datos. Ocurre cuando los datos del usuario (un campo de formulario, un parámetro de URL, un cuadro de búsqueda) se combinan directamente con una consulta SQL como texto sin procesar, en lugar de manejarse de forma segura.

Cómo Funciona la Inyección SQL: Un Ejemplo Sencillo

Imagina un formulario de inicio de sesión cuyo código del backend construye una consulta como esta, pegando directamente los datos del usuario en la cadena SQL:

$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "' AND password = '" . $_POST['password'] . "'";

Esto parece inofensivo con datos normales. Pero si un atacante escribe lo siguiente en el campo del nombre de usuario:

admin' OR '1'='1' -- 

La consulta que la base de datos realmente recibe se convierte en:

SELECT * FROM users WHERE username = 'admin' OR '1'='1' -- ' AND password = '...'

Como '1'='1' siempre es verdadero y -- comenta el resto de la línea (incluida la verificación de la contraseña), esta consulta devuelve la fila del usuario administrador sin necesitar nunca una contraseña válida. El atacante acaba de iniciar sesión sin conocer ninguna credencial.

Por Qué la Inyección SQL Es Tan Peligrosa

Según la base de datos y cómo esté construida la aplicación, la inyección SQL puede permitir a un atacante:

  • Leer datos sensibles: registros de clientes, contraseñas, datos de pago, cualquier cosa de la base de datos.
  • Saltarse la autenticación: iniciar sesión como cualquier usuario, incluidos los administradores, sin contraseña.
  • Modificar o eliminar datos: alterar registros o borrar tablas completas.
  • Escalar aún más: en casos graves, obtener un acceso más amplio al servidor subyacente.

Esta combinación de “fácil de introducir, grave cuando se explota” es justo la razón por la que la inyección SQL ha seguido siendo uno de los riesgos de aplicaciones web más citados de manera constante durante años.

Cómo Prevenir la Inyección SQL

La buena noticia: prevenir la inyección SQL es muy factible una vez que conoces los patrones correctos a seguir.

1. Usa Consultas Parametrizadas (Sentencias Preparadas)

Esta es la defensa más importante. En lugar de construir una consulta concatenando cadenas, envías por separado la estructura de la consulta y los datos del usuario: la base de datos trata la entrada estrictamente como datos, nunca como SQL ejecutable.

PHP (PDO):

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);

Python:

cursor.execute(
    "SELECT * FROM users WHERE username = %s AND password = %s",
    (username, password)
)

En ambos ejemplos, aunque alguien ingrese admin' OR '1'='1' -- como nombre de usuario, se trata como una cadena literal que hay que buscar, no como parte del comando SQL.

2. Usa un ORM o un Constructor de Consultas

Herramientas como SQLAlchemy (Python), Eloquent (PHP/Laravel) o el ORM de Django construyen consultas parametrizadas por ti automáticamente, de modo que obtienes esta protección sin tener que escribir SQL sin procesar a mano en la mayoría de las operaciones cotidianas.

3. Valida y Sanea los Datos de Entrada

Incluso con consultas parametrizadas, es una buena práctica validar los tipos y formatos de los datos (confirmar que un ID realmente es un número, que un correo parece un correo, etc.) como una capa adicional de defensa.

4. Aplica el Principio de Mínimo Privilegio a las Cuentas de la Base de Datos

El usuario de base de datos de tu aplicación solo debe tener los permisos que realmente necesita. Una función de reportes de solo lectura, por ejemplo, no debería conectarse con una cuenta que pueda eliminar tablas.

5. Mantén Actualizados el Software y las Dependencias

Muchas vulnerabilidades reales de inyección SQL provienen de plugins, temas o bibliotecas desactualizados y no del código personalizado. Mantener todo parchado cierra las vulnerabilidades conocidas y divulgadas previamente.

6. Agrega un Firewall de Aplicaciones Web (WAF) como Capa Extra

Un WAF puede detectar y bloquear muchos intentos comunes de inyección SQL antes de que lleguen siquiera a tu aplicación: una red de seguridad útil, aunque nunca un sustituto de las consultas parametrizadas en tu propio código.

Inyección SQL y WordPress

Si construyes con WordPress, la propia API de base de datos de la plataforma ya te protege cuando la usas correctamente. El método $wpdb->prepare() construye automáticamente consultas parametrizadas:

global $wpdb;
$results = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT * FROM {$wpdb->prefix}posts WHERE post_author = %d",
        $author_id
    )
);

La mayoría de las vulnerabilidades de inyección SQL en WordPress provienen de temas o plugins mal programados que construyen consultas concatenando directamente valores de $_GET o $_POST, saltándose por completo $wpdb->prepare(). Al revisar o escribir código personalizado de WordPress, este es exactamente el patrón que debes vigilar.

Conclusión

La inyección SQL sigue siendo una de las vulnerabilidades de aplicaciones web más comunes y más prevenibles: lo bastante peligrosa para exponer o destruir una base de datos completa, pero evitable con un solo hábito constante: nunca construyas una consulta SQL concatenando directamente en ella los datos del usuario.

Las consultas parametrizadas, los ORM, las cuentas de base de datos con mínimo privilegio y mantener el software actualizado forman en conjunto una defensa sólida y por capas contra la inyección SQL. Ya sea que escribas PHP sin procesar, trabajes en Python o construyas sobre WordPress, el mismo principio de fondo se aplica en todas partes: trata los datos del usuario como datos, nunca como código, y la inyección SQL deja de ser una amenaza de la que preocuparse.