Curso
La inyección SQL (o SQLi para abreviar) es uno de los trucos más antiguos del manual del hacker, pero sigue siendo increíblemente común e increíblemente peligroso. En resumen, se trata de engañar a una base de datos para que revele cosas que no debería.
En este artículo, te explicaré qué es realmente la inyección SQL, las distintas formas en que la utilizan los atacantes, algunos ejemplos reales que causaron graves daños y, quizás lo más importante, cómo puedes evitarla. Tanto si eres desarrollador como si simplemente sientes curiosidad por saber cómo se rompen las cosas en Internet, saldrás de aquí con una sólida comprensión de SQLi (sin quedarte dormido a mitad de camino, lo prometo).
¿Qué es la inyección SQL?
La inyección SQL es un tipo de ataque que se produce cuando alguien encuentra la forma de manipular las consultas SQL que tu aplicación envía a la base de datos. Normalmente, esas consultas deben hacer cosas como obtener el perfil de un usuario o actualizar un listado de productos. Pero con SQLi, un atacante puede inyectar fragmentos maliciosos de código SQL en tus campos de entrada (como barras de búsqueda o formularios de inicio de sesión), y de repente la base de datos está haciendo exactamente lo que quiere en su lugar.
¿Por qué funciona?
Porque, en algún punto, la aplicación confía demasiado en las entradas del usuario y las trata como texto inofensivo, en lugar de como código potencialmente ejecutable. Es como dejar que alguien rellene un formulario y luego pegar lo que ha escrito directamente en una consola de comandos.
¿Por qué es malo?
La inyección SQL es peligrosa porque puede utilizarse para ver o robar datos privados (como nombres de usuario, contraseñas o información de tarjetas de crédito), eludir las pantallas de inicio de sesión, borrar o modificar datos e incluso tomar el control total del servidor de la base de datos en el peor de los casos.
Así que sí, SQLi es malo, y ni siquiera es un problema de seguridad reciente, pero te sorprendería ver cuántas aplicaciones no están debidamente protegidas contra él.
Tipos de inyección SQL
Dependiendo de cómo interactúe el atacante con tu aplicación y del tipo de respuesta que obtenga, SQLi tiene varios sabores diferentes. Hay 3 tipos principales con los que te puedes encontrar:
SQLi en banda
Es el tipo más sencillo. El atacante envía una consulta SQL maliciosa y obtiene los resultados a través de la aplicación. Es rápido, y a menudo muy eficaz.
-
SQLi basado en errores: Esta técnica se basa en que la base de datos devuelva mensajes de error. Estos errores pueden revelar un montón de información útil, como los nombres de las tablas o la estructura de las consultas, lo que facilita al atacante la planificación de su próximo movimiento.
-
SQLi basado en uniones: Aquí, el atacante utiliza el operador
UNION
para combinar su propia consulta con la que está ejecutando tu aplicación. Es una forma inteligente de extraer datos adicionales de la base de datos y colarlos en la respuesta.
SQLi inferencial (también conocido como SQLi ciego)
Éste es más sigiloso. En lugar de ver directamente los resultados de su consulta, el atacante observa cómo se comporta la aplicación para averiguar qué ocurre bajo el capó.
- SQLi basado en booleanos (basado en el contenido): El atacante retoca la consulta con condiciones que sean verdaderas o falsas (como 1=1 o 1=2) y observa cómo cambia la página. ¿Se carga normalmente? ¿Mostrar un error? ¿Actuar de forma extraña?
- SQLi basado en el tiempo: Esta técnica añade retardos en la consulta (por ejemplo,
WAITFOR DELAY '00:00:05'
) y utiliza el tiempo de respuesta para deducir si una condición es verdadera.
SQLi fuera de banda (también conocido como "cuando las cosas se ponen raras")
Ésta es menos común, pero aun así merece la pena conocerla. SQLi fuera de banda no depende de respuestas inmediatas de la aplicación. En su lugar, el atacante utiliza canales alternativos como DNS o peticiones HTTP para extraer datos. Suele reservarse para situaciones en las que no es posible una respuesta directa, pero el servidor de la base de datos tiene acceso a Internet (y en el 90% de los casos, probablemente no debería tenerlo).
Técnicas comunes de inyección SQL
Bien, ya hemos aprendido 3 tipos de inyección SQL. Pero, ¿cómo lo consiguen los atacantes en la práctica?
O 1=1 ataque
Éste es un clásico. Imagina un formulario de acceso en el que debes introducir tu nombre de usuario y contraseña. Un atacante podría introducir algo como esto
' OR 1=1 --
La consulta SQL acaba pareciendo
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = '';
Como 1=1
es siempre verdadero, la base de datos devuelve todos los usuarios, y --
convierte el resto de la consulta en un comentario. Si no hay ningún límite, el atacante podría conectarse sin ni siquiera conocer un nombre de usuario válido.
Fuente: vmware
Inyección de comentarios
Como acabamos de ver, los caracteres--
o /* */
se utilizan para comentar partes de una sentencia SQL. Los atacantes utilizan esto para eliminar cualquier cláusula extra que pudiera romper su carga útil inyectada. Por ejemplo, si no conocen la estructura completa de la consulta original, pueden simplemente cortarla y hacerla sintácticamente válida de nuevo.
Sentencias SQL por lotes
Algunas bases de datos permiten ejecutar varias sentencias SQL en una sola petición, separadas por punto y coma. Esta función puede ser utilizada por los hackers para hacer todo tipo de daño, como modificar datos o incluso eliminar tablas si la aplicación no lo restringe.
'; DROP TABLE users; --
Ataques basados en UNION
Al inyectar una sentenciaUNION SELECT
, los atacantes pueden combinar su consulta maliciosa con la legítima y recuperar resultados de otras tablas, como datos sensibles de usuarios, contraseñas o información de tarjetas de crédito. Básicamente se trata de utilizar una consulta existente para obtener datos adicionales.
Inyección SQL ciega
Ya lo hemos mencionado antes. Incluso cuando la aplicación no muestra errores ni devuelve resultados de consultas, los atacantes pueden extraer datos poco a poco observando el comportamiento. Es más lento y tedioso, pero funciona. Esto suele automatizarse mediante herramientas que pueden probar cientos de consultas y respuestas en función del tiempo.
Inyección SQL almacenada
El SQL malicioso se guarda en la base de datos, como en un perfil de usuario o en un comentario, y se ejecuta más tarde cuando alguien consulta esos datos.
Ataques de inyección SQL en el mundo real
La inyección SQL puede parecer un asunto de hackers de nicho, pero ha causado daños muy reales a lo largo de los años. Y por daños me refiero a millones de registros de usuarios expuestos, enormes multas y titulares que no hicieron ningún favor a los departamentos de marketing.
Guess.com (2002)
Este es un ejemplo temprano que hizo que la gente empezara a prestar atención. Un investigador de seguridad explotó un fallo de inyección SQL y obtuvo acceso a más de 200.000 registros de clientes, incluidos datos de tarjetas de crédito. La buena noticia es que fue encontrado y denunciado por un hacker ético.
Sistemas de pago Heartland (2009)
Se trató de una brecha masiva que afectó a un procesador de pagos y se robaron más de 130 millones de números de tarjetas de crédito. Los atacantes utilizaron la inyección SQL para conseguir un punto de apoyo, y luego escalaron desde allí. Ésta se cita a menudo como una de las mayores violaciones de datos de la historia.
¡Yahoo! Voces (2012)
Los atacantes explotaron un fallo de inyección SQL basado en UNION y expusieron 450.000 nombres de usuario y contraseñas en texto plano. Sí, has leído bien, credenciales sin procesar en texto plano. Esa filtración fue especialmente embarazosa porque Yahoo! era una gran empresa tecnológica, y almacenar contraseñas sin cifrar es un grave "no hacer", incluso para los estándares de 2012.
TalkTalk (2015)
TalkTalk es un proveedor de telecomunicaciones británico de alto perfil que fue víctima de un ataque de inyección SQL bastante básico. Se vieron comprometidos unos 157.000 registros de clientes, y la empresa fue multada con 400.000 £. Uno de los agresores sólo tenía 17 años.
Gab (2021)
Los hacktivistas utilizaron la inyección SQL para filtrar 70 GB de datos, incluidos mensajes privados y contraseñas cifradas. La brecha tuvo una fuerte carga política, y las consecuencias provocaron un escrutinio aún mayor de la postura de seguridad general de Gab.
Cómo evitar la inyección SQL
Vale, ahora que nos hemos asustado un poco con todas esas brechas del mundo real, hablemos de soluciones. La buena noticia es que evitar la inyección SQL no es ciencia espacial. La mayoría de las veces, se trata de no confiar en las aportaciones de los usuarios y atenerse a las mejores prácticas. Esto es lo que puedes hacer:
Utilizar consultas parametrizadas
Esta es la regla número uno. Nunca construyas consultas SQL pegando cadenas. En su lugar, utiliza marcadores de posición y pasa las entradas del usuario como parámetros. La mayoría de los frameworks y bibliotecas lo hacen superfácil.
Por ejemplo en Node.js con pg (PostgreSQL):
client.query('SELECT * FROM users WHERE id = $1', [userId]);
Esto básicamente le dice a la base de datos, "Aquí está la estructura de la consulta, y aquí hay algunos datos, por favor, no los mezcles".
Utiliza los procedimientos almacenados de forma inteligente
Los procedimientos almacenados pueden ayudar, pero sólo si también evitan el SQL dinámico. La idea es que la lógica SQL viva en la base de datos, y tu aplicación sólo llame a esos trozos seguros y predefinidos de lógica.
Si quieres aprender a crear, actualizar y ejecutar funciones y procedimientos almacenados, echa un vistazo a nuestro curso Escribir funciones y procedimientos almacenados en SQL Server.
Validar y limpiar la entrada
Si tu aplicación espera un número, asegúrate de que sea un número. No aceptes ciegamente todo lo que te lance un usuario. Utiliza comprobaciones de tipo, límites de longitud y listas de permitidos (por ejemplo, sólo permitir valores buenos conocidos) siempre que sea posible.
Escapar caracteres (como las comillas) también puede ayudar, pero no sustituye a las consultas parametrizadas.
Utiliza un cortafuegos de aplicaciones web (WAF)
Un WAF puede actuar como primera línea de defensa, especialmente contra patrones de ataque conocidos. Puede ayudar a bloquear el tráfico malicioso incluso antes de que llegue a tu aplicación. No es infalible pero sí útil, es un poco como un filtro de spam para tu SQL.
Aplicar el principio del menor privilegio
Tu aplicación web no debería conectarse a la base de datos con derechos de administrador. Limita lo que puede hacer cada usuario o servicio. Por ejemplo, si tu aplicación sólo necesita leer datos, no le des permiso para borrar tablas. Cuanta menos potencia tenga, menos daño puede hacer una inyección.
Pruebas y detección de inyecciones SQL
Aunque creas que tu código es seguro, merece la pena probarlo como lo haría un atacante. La inyección SQL tiene una forma de pasar desapercibida, especialmente en grandes bases de código o sistemas heredados. Hay herramientas y técnicas que facilitan mucho la detección y con las que es bastante divertido jugar.
Pruebas manuales
A veces, la forma más rápida de detectar un agujero es simplemente hurgar en él. Prueba a introducir ' OR 1=1 -- or '; DROP TABLE users; --
en campos de formulario, URL o cualquier otra área de entrada y comprueba cómo reacciona la aplicación. Si obtienes errores extraños, datos inesperados o misteriosos mensajes de éxito, puede que hayas encontrado algo sospechoso.
Consejo profesional: Prueba siempre en un entorno de desarrollo o de ensayo.
Escáneres automatizados
Hay muchas herramientas que se encargarán de pinchar por ti. Algunas buenas:
- sqlmap: Una bestia de código abierto que automatiza la detección y la explotación (en contextos de pruebas éticas).
- Burp Suite: Excelente para la seguridad de aplicaciones web en general, con extensiones para la detección de SQLi.
- OWASP ZAP: Gratuito y apto para principiantes, creado para encontrar todo tipo de vulnerabilidades web.
Estas herramientas simulan ataques, señalan posibles puntos de inyección y, a veces, pueden sugerir soluciones.
Análisis de registros
Otro truco astuto: controla los registros de tu base de datos. Las consultas fallidas repetidas, los patrones de sintaxis extraños o una oleada de solicitudes con ', --
,
o UNION SELECT
son señales de alarma.
Conclusión
La inyección SQL no va a desaparecer pronto, y es una de esas amenazas que nunca pasan de moda. Es simple, es potente y, si no tienes cuidado, puede causar graves daños. La cuestión es que el SQLi es totalmente evitable. Utilizando consultas parametrizadas, validando las entradas, aplicando el principio del menor privilegio y realizando pruebas con regularidad, puedes proteger tus aplicaciones y a tus usuarios del devastador impacto de un ataque de inyección SQL.
Recuerda, nadie espera la perfección, pero con un poco de esfuerzo proactivo, puedes mantener a salvo tu base de datos y tacharla de tu lista de control de seguridad. Y si te tomas en serio el SQL y quieres mostrar tus habilidades a posibles empleadores, ¡echa un vistazo a nuestra Certificación de Asociado SQL! Demostrará que eres capaz de utilizar SQL para extraer los datos adecuados de una base de datos, y utilizarlo para responder a preguntas habituales sobre datos.
Preguntas frecuentes
¿Se puede utilizar la inyección SQL para atacar bases de datos NoSQL?
La inyección SQL tradicional no funciona en bases de datos NoSQL como MongoDB, pero pueden producirse ataques similares de tipo inyección si las entradas no se desinfectan correctamente (como inyecciones de documentos o manipulación de consultas).
¿Cómo ayudan los marcos modernos a evitar la inyección SQL?
Muchos frameworks modernos (como Django, Laravel o Spring) incluyen protecciones integradas como capas ORM y parametrización automática, que hacen más difícil escribir accidentalmente consultas vulnerables. Pero aún así, ¡tienes que utilizarlos correctamente!
¿Las aplicaciones móviles también corren el riesgo de sufrir inyecciones SQL?
Absolutamente. Si una aplicación móvil se comunica con una API backend que construye consultas SQL inseguras basadas en la entrada del usuario, es igual de vulnerable aunque el frontend parezca bloqueado.
¿Cómo encuentran los atacantes sitios web vulnerables para utilizar la inyección SQL?
A menudo utilizan escáneres automatizados o "Google dorking" (consultas de búsqueda especiales) para encontrar páginas con campos de entrada o parámetros de URL que puedan ser explotables.