system onlinepath: /guias/hacking/sql-injection-como-detectar-y-prevenir-inyecciones/mode: knowledge_baselocal:
Hacking ético · Nivel intermedio

SQL Injection: cómo detectar y prevenir inyecciones SQL

La inyección SQL existe hace más de dos décadas y sigue entre las vulnerabilidades más graves, porque cuando ocurre, un atacante puede leer, alterar o borrar toda la base de datos. Y tiene una defensa casi perfecta.

13 min de lectura▣ Actualizada el ◇ Por Underc0de
Respuesta rápida

La inyección SQL (SQL injection o SQLi) es una vulnerabilidad que permite a un atacante alterar las consultas que una aplicación hace a su base de datos, introduciendo fragmentos de SQL en un campo de entrada. Cuando funciona, las consecuencias son gravísimas: el atacante puede leer datos que no debería (contraseñas, datos personales, todo lo de la base), modificarlos o borrarlos, e incluso saltarse el inicio de sesión. Por eso, pese a existir hace más de dos décadas, sigue entre las vulnerabilidades más críticas del OWASP Top 10. La causa raíz es la misma que la del XSS: la aplicación mezcla datos con código, arma la consulta pegando directamente lo que escribió el usuario, de modo que si el usuario escribe SQL, la base lo ejecuta como parte de la consulta. La defensa es casi perfecta y se llama consultas parametrizadas (o sentencias preparadas): separar el código SQL de los datos, enviando la estructura de la consulta y los valores por caminos distintos, de forma que los datos nunca se interpreten como código. Se refuerza con validación de entrada y el mínimo privilegio de la cuenta de base de datos. Guía defensiva: entender el ataque para prevenirlo, en sistemas propios o autorizados.

Ver índice de contenidos
  1. 01Qué es y por qué es tan grave
  2. 02La causa raíz
  3. 03La defensa definitiva
  4. 04Cómo detectarla
  5. 05Errores frecuentes
  6. 06Preguntas frecuentes
  7. 07Fuentes

Qué es y por qué es tan grave

Casi toda aplicación guarda sus datos en una base de datos y los consulta con SQL, un lenguaje para pedir, insertar, modificar o borrar datos. La inyección SQL ocurre cuando un atacante consigue que su propia entrada se convierta en parte del SQL que la aplicación ejecuta, «inyectando» comandos que el desarrollador no previó.

El acceso a toda la base es el premio

La gravedad del SQLi viene de qué pone en juego: la base de datos, donde vive todo —usuarios, contraseñas, datos personales, información de negocio—. Una inyección exitosa puede leer cualquier tabla (extraer la base entera), modificar o borrar datos, saltarse la autenticación (entrar sin contraseña alterando la consulta de login) y, en casos graves, comprometer el servidor. Es uno de los ataques de mayor impacto, y por eso lleva décadas encabezando las listas de riesgos pese a ser bien conocido.

La causa raíz

Cómo funciona la inyección SQL y cómo se previene, mostrado como un contraste entre el código vulnerable y el código seguro. Arriba, la causa raíz: una aplicación necesita consultar su base de datos, por ejemplo para buscar un usuario por su nombre, y construye la consulta SQL pegando directamente dentro del texto de la consulta lo que el usuario escribió en un campo de entrada. Se ilustra el caso vulnerable: la aplicación arma la consulta concatenando el nombre ingresado, de modo que si el usuario escribe un nombre normal la consulta funciona bien, pero si en lugar de un nombre escribe fragmentos de SQL cuidadosamente diseñados, esos fragmentos pasan a formar parte de la consulta y la base de datos los ejecuta como comandos, no como un simple dato. Un ejemplo clásico muestra cómo una entrada maliciosa puede convertir una consulta de inicio de sesión en una que siempre da verdadero, permitiendo entrar sin conocer la contraseña, o agregar comandos para leer otras tablas. La idea central resaltada es que la vulnerabilidad nace de mezclar datos con código: la aplicación no distingue entre lo que es un dato para buscar y lo que son instrucciones para ejecutar, y por eso la base termina interpretando como código lo que el usuario escribió. Abajo, la defensa definitiva, las consultas parametrizadas también llamadas sentencias preparadas: en lugar de pegar el dato dentro del texto de la consulta, se envía la estructura de la consulta con marcadores de posición por un lado, y los valores de los datos por otro lado y por un canal separado; de esta forma la base de datos recibe primero la estructura fija de la consulta y luego los datos, y trata a los datos siempre como datos, nunca como código ejecutable, sin importar lo que contengan. Así, aunque un usuario escriba fragmentos de SQL en el campo, se buscarán literalmente como texto en lugar de ejecutarse, y el ataque queda neutralizado de raíz. Se destaca que esta defensa es casi perfecta y que los marcos de acceso a bases de datos modernos la ofrecen de forma estándar. A la derecha, las defensas de refuerzo o en profundidad: validar las entradas para rechazar en el origen lo que no tenga sentido, y aplicar el principio de mínimo privilegio a la cuenta de base de datos que usa la aplicación, de modo que si aun así ocurriera una inyección, esa cuenta solo pueda hacer lo estrictamente necesario y el daño quede acotado. Al pie, dos aclaraciones: que la inyección SQL comparte exactamente la misma causa raíz que el Cross-Site Scripting, es decir confundir datos con código, y que la guía es defensiva y educativa, orientada a prevenir la vulnerabilidad en el propio código o en sistemas autorizados, nunca a atacar bases de datos ajenas.
La causa raíz: armar la consulta pegando la entrada del usuario, que así puede ejecutar SQL. La defensa: consultas parametrizadas, que envían estructura y datos por caminos separados y tratan los datos como datos.

El SQLi nace de un error de construcción muy concreto. Cuando una aplicación necesita, por ejemplo, buscar un usuario por su nombre, tiene que armar una consulta SQL. La forma insegura es pegar el nombre que escribió el usuario directamente dentro del texto de la consulta:

texto
# VULNERABLE: se pega la entrada del usuario dentro de la consulta
consulta = "SELECT * FROM usuarios WHERE nombre = '" + entrada + "'"

# Si el usuario escribe un nombre normal, funciona.
# Si escribe SQL diseñado, la base lo ejecuta como comando.
i
Mezclar datos con código

El problema es que la aplicación no distingue entre lo que es un dato (el nombre a buscar) y lo que son instrucciones (el SQL). Al pegar la entrada dentro de la consulta, si el usuario escribe fragmentos de SQL en vez de un nombre, esos fragmentos pasan a formar parte de la consulta y la base los ejecuta. Es exactamente la misma causa raíz que el XSS: confundir datos con código. Toda la familia de inyecciones nace de ahí, y por eso la solución también es común: separar los datos del código.

La defensa definitiva

La buena noticia del SQLi es que tiene una defensa casi perfecta, conocida y disponible en todos los lenguajes: las consultas parametrizadas (también llamadas sentencias preparadas).

texto
# SEGURO: la estructura va por un lado, el dato por otro
consulta = "SELECT * FROM usuarios WHERE nombre = ?"
ejecutar(consulta, [entrada])   # el dato se pasa aparte

La idea: en vez de pegar el dato dentro del texto de la consulta, se envía la estructura de la consulta con marcadores de posición (el ?) por un lado, y los valores por otro camino. La base de datos recibe primero la estructura fija y luego los datos, y trata a los datos siempre como datos, nunca como código ejecutable, sin importar lo que contengan. Así, aunque el usuario escriba SQL en el campo, se busca literalmente como texto en lugar de ejecutarse: el ataque queda neutralizado de raíz.

Los marcos de acceso a bases de datos modernos (los ORM y las bibliotecas estándar) ofrecen consultas parametrizadas de forma natural, y por eso previenen el SQLi cuando se usan bien. Sobre esta defensa central se suman dos refuerzos de defensa en profundidad: validar las entradas (rechazar en el origen lo que no tenga sentido) y aplicar el mínimo privilegio a la cuenta de base de datos que usa la aplicación —que solo pueda hacer lo estrictamente necesario—, para que si algo fallara, el daño quede acotado.

Cómo detectarla

Para encontrar SQLi en tu propio código (o en sistemas que auditás con autorización), hay varios caminos, del más simple al más automatizado:

  • Revisar el código buscando dónde se arman consultas pegando entrada del usuario. Cada concatenación de una variable de entrada dentro de una consulta es un candidato. Esta revisión, manual o con herramientas de análisis estático, es la más directa.
  • Herramientas de análisis (estático, que revisa el código; y dinámico, que prueba la aplicación en ejecución) que detectan patrones de inyección.
  • Pruebas de seguridad en un entorno controlado: enviar entradas de prueba y observar si la aplicación se comporta de forma anómala. Esto es parte de una gestión de vulnerabilidades ordenada.
!
Solo en sistemas propios o con autorización

Probar inyecciones SQL contra un sitio que no es tuyo y para el que no tenés permiso explícito es ilegal, sin importar la intención. El hacking ético se define por operar dentro de un marco legal y autorizado. Para practicar la detección y explotación de SQLi de forma segura, existen laboratorios y entornos vulnerables a propósito pensados para eso. Aprender el ataque tiene un único fin legítimo: prevenirlo en lo propio.

Errores frecuentes

  • Armar consultas pegando la entrada del usuario. La causa directa del SQLi; usar consultas parametrizadas.
  • Confiar solo en filtrar caracteres. Escapar a mano siempre deja huecos; la parametrización es la solución.
  • Creer que validar la entrada alcanza. Ayuda, pero la defensa que cierra el problema es separar datos de código.
  • Cuenta de base de datos con todos los privilegios. Si hay una inyección, el atacante hereda ese poder; mínimo privilegio.
  • Mensajes de error que revelan la base. Ayudan al atacante a afinar la inyección; no exponer detalles internos.
  • Pensar que es un problema del pasado. Sigue entre los riesgos más comunes y graves.
  • Probar SQLi en sitios ajenos. Es ilegal; usar solo entornos propios o de práctica.

Preguntas frecuentes

¿Qué es la inyección SQL?

La inyección SQL, conocida también como SQL injection o SQLi, es una vulnerabilidad que permite a un atacante alterar las consultas que una aplicación realiza a su base de datos, introduciendo fragmentos del lenguaje SQL a través de un campo de entrada. Casi todas las aplicaciones almacenan su información en una base de datos y la consultan mediante SQL, que es el lenguaje para pedir, insertar, modificar o borrar datos. La inyección ocurre cuando el atacante consigue que su propia entrada se convierta en parte del SQL que la aplicación ejecuta, colando comandos que quien programó nunca previó. Cuando el ataque funciona, las consecuencias son sumamente graves, porque la base de datos es donde reside toda la información sensible: el atacante puede leer datos que no debería ver, como contraseñas y datos personales de todos los usuarios, puede modificarlos o borrarlos, puede saltarse el proceso de inicio de sesión alterando la consulta que valida las credenciales, y en los casos más graves puede llegar a comprometer el servidor. Por todo ello, a pesar de ser una vulnerabilidad conocida desde hace más de dos décadas, sigue figurando entre las más críticas y frecuentes en las listas de riesgos de seguridad.

¿Por qué sigue siendo tan grave un problema tan antiguo?

Sigue siendo grave por la combinación de dos factores: el enorme impacto que tiene cuando ocurre y la facilidad con que se vuelve a introducir si no se siguen las buenas prácticas. En cuanto al impacto, una inyección SQL exitosa pone en juego la base de datos completa, que es el corazón de casi cualquier aplicación y contiene la información más sensible, de modo que un solo fallo puede exponer o destruir todos los datos, saltarse la autenticación e incluso servir de trampolín hacia el servidor. En cuanto a la persistencia, aunque la defensa es conocida y casi perfecta, basta con que en algún punto del código alguien arme una consulta pegando directamente la entrada del usuario para reabrir la vulnerabilidad, algo que sigue ocurriendo por desconocimiento, por descuido, por código antiguo heredado o por atajos durante el desarrollo. Es decir, el problema no persiste porque no tenga solución, sino porque la solución hay que aplicarla de forma consistente en cada consulta, y un único descuido reintroduce el riesgo. Por eso figura desde hace años en las listas de vulnerabilidades más críticas: no por falta de remedio, sino por lo caro que resulta cuando el remedio no se aplica en todos lados.

¿Cuál es la causa raíz de la inyección SQL?

La causa raíz es que la aplicación mezcla datos con código al construir sus consultas. Cuando una aplicación necesita, por ejemplo, buscar un usuario por su nombre, tiene que armar una consulta SQL, y la forma insegura de hacerlo consiste en pegar directamente el texto que escribió el usuario dentro del texto de la consulta. El problema es que, al hacerlo así, la aplicación no distingue entre lo que es un dato, en este caso el nombre a buscar, y lo que son instrucciones, es decir el propio lenguaje SQL. Si el usuario escribe un nombre normal, la consulta funciona correctamente, pero si en lugar de un nombre introduce fragmentos de SQL cuidadosamente diseñados, esos fragmentos pasan a formar parte de la consulta y la base de datos los ejecuta como comandos en lugar de tratarlos como un simple valor a buscar. Esta confusión entre datos e instrucciones es exactamente la misma que origina el Cross-Site Scripting y, en general, toda la familia de ataques de inyección. Entenderla es clave porque revela que la defensa no consiste en perseguir cada truco de ataque, sino en resolver la raíz separando de forma sistemática los datos del código.

¿Qué son las consultas parametrizadas y por qué son la defensa?

Las consultas parametrizadas, también llamadas sentencias preparadas, son la defensa casi perfecta contra la inyección SQL, disponible en todos los lenguajes de programación modernos. Su idea es sencilla y poderosa: en lugar de pegar el dato dentro del texto de la consulta, se envía por un lado la estructura de la consulta con marcadores de posición donde irán los valores, y por otro lado y por un canal separado se envían los valores de esos datos. De este modo, la base de datos recibe primero la estructura fija de la consulta y luego los datos, y trata a los datos siempre como datos, nunca como código ejecutable, sin importar lo que contengan. La consecuencia es que, aunque un usuario escriba fragmentos de SQL en el campo de entrada, esos fragmentos se buscarán literalmente como texto en lugar de ejecutarse, con lo que el ataque queda neutralizado de raíz y no por un filtro que podría fallar. Es una solución estructural y no un parche. Los marcos de acceso a bases de datos y las bibliotecas estándar modernas ofrecen consultas parametrizadas de forma natural, por lo que previenen la inyección SQL cuando se usan correctamente, y por eso son la recomendación central de todas las guías de seguridad sobre el tema.

¿Basta con validar las entradas para prevenir el SQLi?

Validar las entradas ayuda y es recomendable, pero por sí sola no es suficiente para prevenir la inyección SQL, y confiar únicamente en ella es un error común. La validación consiste en comprobar en el origen que los datos recibidos tienen sentido para el campo correspondiente y en rechazar lo que no cumpla, lo cual reduce la superficie de ataque y aporta valor como defensa en profundidad. Sin embargo, no ataca la causa raíz del problema, que es la mezcla de datos con código en la construcción de la consulta, y siempre es posible que alguna entrada maliciosa válida en apariencia logre colarse, o que la validación tenga un hueco. La defensa que realmente cierra el problema son las consultas parametrizadas, porque garantizan a nivel estructural que los datos nunca se interpreten como código, independientemente de su contenido. Por eso el enfoque correcto es combinar ambas cosas con una jerarquía clara: las consultas parametrizadas como defensa principal e indispensable, y la validación de entradas junto con el principio de mínimo privilegio de la cuenta de base de datos como refuerzos que acotan aún más el riesgo. La validación complementa, pero no reemplaza, a la parametrización.

¿Puedo practicar inyección SQL para aprender a defenderme?

Sí, y es una forma excelente de comprender a fondo la vulnerabilidad y cómo prevenirla, pero debe hacerse exclusivamente en entornos propios o específicamente diseñados para la práctica, nunca contra sistemas ajenos. Probar inyecciones SQL contra un sitio que no te pertenece y para el que no tenés autorización explícita es ilegal, sin importar que la intención sea aprender o que no causes un daño evidente; el hacking ético se define precisamente por operar siempre dentro de un marco legal y autorizado. Para aprender de manera segura existen laboratorios y aplicaciones deliberadamente vulnerables, creados con el propósito de que las personas practiquen la detección y explotación de vulnerabilidades como el SQLi en un entorno controlado y legal. En esos entornos podés experimentar con las técnicas de ataque, observar cómo una entrada maliciosa altera una consulta, y luego comprobar cómo las consultas parametrizadas neutralizan el problema. El objetivo legítimo de aprender cómo funciona el ataque es siempre poder prevenirlo en tus propios sistemas o en aquellos que audites con permiso, y ese conocimiento aplicado con responsabilidad y dentro de la ley es una herramienta valiosa para construir aplicaciones más seguras.

Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.

Aportes de la comunidad Underc0de

  1. Underc0de, foro. Sección Hacking. Vulnerabilidades y auditoría de aplicaciones web.
  2. Underc0de, foro. Sección Desarrollo web. Desarrollo seguro con bases de datos.

Documentación oficial

  1. OWASP. SQL Injection. Descripción de referencia, citada en la guía.
  2. OWASP. SQL Injection Prevention Cheat Sheet. Cómo prevenirla.
  3. MITRE. CWE-89. La debilidad de inyección SQL catalogada.
  4. OWASP. OWASP Top 10. La inyección entre los riesgos principales.