¿Qué es SQL Injection? Cómo funciona y cómo evitarla

¿Qué es SQL Injection? Cómo funciona y cómo evitarla

Escribes en el campo de usuario de una pantalla de login y, en lugar de un nombre, pegas un fragmento de código. El sitio no se queja: lo ejecuta. Así funciona, en esencia, SQL Injection, una falla descrita públicamente hace más de 25 años y que sigue apareciendo en incidentes de gran escala. Este post explica el mecanismo con un ejemplo que se entiende sin ser programador y muestra qué resuelve realmente el problema.

¿Qué es SQL Injection?

¿Qué es SQL Injection en una frase?

SQL Injection es un ataque en el que el invasor inserta comandos SQL en un campo de entrada (formulario, URL, cookie) y la aplicación los ejecuta en la base de datos como si fueran parte de la consulta legítima.

SQL es el lenguaje que usan las aplicaciones para hablar con bases de datos como MySQL, PostgreSQL y SQL Server. El problema nace cuando el programador arma la consulta uniendo texto fijo con lo que escribió el usuario. A partir de ahí, la base de datos no puede distinguir qué es comando del programador y qué es dato del usuario.

Cómo funciona el ataque, paso a paso

Imagina un login que ejecuta esta consulta, armada por concatenación de texto:

SELECT * FROM usuarios
WHERE login = 'INPUT_LOGIN' AND senha = 'INPUT_SENHA';

Si el invasor escribe admin'-- en el campo de login, la consulta queda así:

SELECT * FROM usuarios
WHERE login = 'admin'--' AND senha = '';

En SQL, -- inicia un comentario. Todo lo que viene después se ignora, incluida la verificación de la contraseña. La base devuelve al usuario admin y la aplicación lo deja entrar. No se rompió ninguna contraseña ni se instaló ningún malware: el propio sistema hizo el trabajo.

¿Qué puede hacer un atacante además de saltarse el login?

Según los permisos de la base de datos, puede leer tablas enteras (usuarios, correos, hashes de contraseñas, tarjetas), modificar o borrar datos y, en configuraciones malas, llegar a ejecutar comandos en el servidor. Las variantes más comunes son:

  • In-band (clásico): el resultado de la consulta inyectada aparece en la propia página, usando UNION SELECT para extraer datos de otras tablas.
  • Basado en errores: los mensajes de error de la base filtran nombres de tablas y columnas.
  • Blind (a ciegas): la página no muestra datos, pero el atacante deduce información por el comportamiento (respuesta verdadera o falsa, tiempo de respuesta) y extrae el contenido bit a bit, normalmente con herramientas automatizadas como sqlmap.

Encontrar objetivos también es barato. Técnicas de búsqueda como las explicadas en Google Dorks: cómo los hackers usan Google para encontrar datos expuestos ayudan a listar páginas con parámetros en la URL, candidatas a prueba.

Casos reales: el ataque no es cosa del pasado

  • Heartland, Hannaford y 7-Eleven (2008–2009): el Departamento de Justicia de EE. UU. acusó formalmente a Albert Gonzalez y otros en agosto de 2009. Según la acusación, el grupo usó SQL injection para instalar sniffers en los servidores de las empresas e interceptar datos de tarjetas, con más de 130 millones de números de tarjetas de crédito y débito robados. CSO Online y Computerworld registraron el caso en su momento.
  • Sony (2011): el grupo LulzSec afirmó haber accedido a datos de Sony Online Entertainment mediante SQL injection, como contamos en PSN fuera de línea: el hackeo que expuso 77 millones de cuentas en 2011.
  • MOVEit Transfer (2023): la CVE-2023-34362 era una falla de SQL injection explotada a gran escala y se convirtió en uno de los mayores ataques a la cadena de suministro de la década, detallado en MOVEit: 3 años del zero-day que expuso 93 millones de registros.

La inyección de código figura en la categoría "Injection" del OWASP Top 10 (A03:2021), uno de los riesgos más conocidos de las aplicaciones web.

Cómo evitar SQL Injection

¿Cuál es la defensa más eficaz contra SQL Injection?

Usar consultas parametrizadas (prepared statements), que mantienen separados el código SQL y los datos del usuario, de modo que la entrada nunca pueda alterar la estructura de la consulta. Es la primera defensa recomendada por la SQL Injection Prevention Cheat Sheet de OWASP.

Ejemplo en Python con sqlite3 (el mismo principio vale en PHP/PDO, Java/JDBC, C# y Node):

# Vulnerable: concatenación
cur.execute("SELECT * FROM usuarios WHERE login = '" + login + "'")

# Seguro: parámetro
cur.execute("SELECT * FROM usuarios WHERE login = ?", (login,))

Con el parámetro, admin'-- se trata como un nombre de usuario raro, no como SQL.

Otras capas, por orden de importancia:

  1. Mínimo privilegio en la base de datos: la cuenta de la aplicación no debe ser dueña de la base ni tener permisos de administrador. Si el ataque pasa, el daño queda limitado.
  2. Validación por lista permitida: para campos que no aceptan parámetro (nombre de columna, orden), acepta solo valores predefinidos. OWASP desaconseja confiar únicamente en el escape de caracteres.
  3. Ocultar mensajes de error detallados al usuario final; regístralos en el log, no en pantalla.
  4. WAF como complemento: ayuda a bloquear patrones conocidos, pero no sustituye corregir el código.
  5. Actualizar software de terceros: en el caso de MOVEit, el código vulnerable no era de las víctimas. Parchear rápido y tener un inventario de sistemas expuestos importa tanto como el código propio.
  6. Hash de contraseñas robusto: si una tabla se filtra, el daño baja mucho. Mira también el caso Adobe 2013 y lo que no se debe hacer con las contraseñas.

¿Y si no eres desarrollador?

No puedes corregir el código del sitio, pero sí controlas el daño cuando se filtra: usa una contraseña única por servicio en un gestor (cómo usar Bitwarden), activa el 2FA y comprueba si tu correo apareció en filtraciones. Si administras un sitio (WordPress, tienda, sistema interno), mantén plugins y temas actualizados, porque la mayoría de las fallas de SQL injection en sitios pequeños vienen de plugins desactualizados.

La lección mayor

SQL Injection es un error de diseño: mezclar comando y dato en el mismo texto. La corrección también es de diseño y no depende de un filtro mágico. Si quieres seguir el hilo de los ataques a credenciales después de una filtración, lee Credential Stuffing: qué es y cómo funciona.

Comentarios