Qué es una inyección SQL y cómo proteger un sitio web

Una inyección SQL ocurre cuando una aplicación permite que datos controlados por un usuario cambien la estructura o el significado de una consulta enviada a la base de datos. El problema suele aparecer al construir instrucciones SQL concatenando texto recibido desde formularios, parámetros de URL, cookies, cabeceras o integraciones externas.

La defensa no consiste en buscar palabras sospechosas. La solución principal es separar la instrucción SQL de sus valores mediante consultas preparadas y parámetros, además de limitar los permisos de la cuenta utilizada por la aplicación.

Qué puede provocar una inyección SQL

El impacto depende de la consulta vulnerable, del motor de base de datos y de los privilegios disponibles. Un atacante podría intentar leer datos privados, omitir controles de acceso, modificar registros, crear usuarios, eliminar información o afectar la disponibilidad del sitio.

Si la aplicación se conecta con una cuenta administrativa, una falla pequeña puede tener consecuencias mucho mayores. Por eso el principio de mínimos privilegios es importante incluso cuando el código parece estar correctamente protegido.

Cómo aparece la vulnerabilidad

El patrón peligroso es crear una consulta uniendo fragmentos de SQL con valores que todavía no fueron separados como datos. Esto puede ocurrir en búsquedas, filtros, inicios de sesión, paneles administrativos, tareas programadas o procesos que importan archivos.

Los datos almacenados tampoco deben considerarse confiables automáticamente. Un valor guardado en una operación puede utilizarse más tarde para construir otra consulta vulnerable. A este escenario se lo suele denominar inyección de segundo orden.

Consultas preparadas y parámetros

Una consulta preparada define primero la estructura de la instrucción y luego vincula los valores mediante parámetros. Así, el motor puede distinguir el código SQL de los datos, aunque un valor contenga comillas u otros caracteres especiales.

Utilizá la API de parámetros que proporciona el lenguaje, framework o CMS. En PHP pueden emplearse PDO o MySQLi con parámetros; en WordPress corresponde utilizar las funciones preparadas de la capa de base de datos. No agregues manualmente comillas alrededor de un marcador ni vuelvas a concatenar el valor después de prepararlo.

Los identificadores dinámicos requieren otro tratamiento

Los parámetros suelen servir para valores, pero no siempre pueden reemplazar nombres de tablas, columnas o palabras como ASC y DESC. Si la aplicación permite elegir alguno de esos elementos, traducí la opción recibida a una lista cerrada definida por el servidor.

Por ejemplo, una opción visible como “fecha” puede mapearse internamente a una columna conocida. Nunca uses directamente el texto proporcionado por el visitante como nombre de columna o fragmento de consulta.

Validación de entradas

Validá tipo, longitud, rango y formato antes de procesar un dato. Un identificador numérico debe convertirse y comprobarse como número; una opción debe pertenecer al conjunto admitido. La validación reduce estados inesperados y mejora los mensajes de error.

Sin embargo, validar no reemplaza los parámetros. Las reglas cambian, algunas entradas legítimas contienen caracteres especiales y una lista de términos bloqueados puede evadirse. La protección debe mantenerse aunque la validación falle o se modifique en el futuro.

Por qué escapar cadenas no es suficiente

Escapar manualmente depende del motor, la codificación, el modo de conexión y el contexto de la consulta. Es fácil omitir un caso o aplicar la función incorrecta. Las consultas parametrizadas ofrecen una separación estructural más sólida y deberían ser la opción predeterminada.

Los procedimientos almacenados tampoco garantizan seguridad por sí solos. Si construyen SQL dinámico concatenando valores, pueden introducir el mismo problema. Deben recibir parámetros y evitar la ejecución de cadenas creadas con entradas externas.

Aplicar mínimos privilegios en la base de datos

  • Creá una cuenta exclusiva para la aplicación y no utilices el usuario administrador.
  • Concedé solamente acceso a las bases, tablas y operaciones que necesita.
  • Separá, cuando sea viable, las tareas de lectura, escritura y administración.
  • No permitas operaciones sobre archivos o funciones de alto privilegio si la aplicación no las requiere.
  • Guardá las credenciales fuera del directorio público y evitá publicarlas en repositorios o copias descargables.

Para operaciones administrativas legítimas, consultá cómo administrar una base de datos con phpMyAdmin en cPanel. Esa herramienta debe estar protegida y no sustituye las buenas prácticas del código.

Errores, registros y monitoreo

El visitante no debería recibir consultas, rutas internas ni detalles del motor. Mostrá un mensaje genérico y registrá la información técnica en un lugar protegido, con acceso restringido y una política de conservación adecuada.

Supervisá errores repetidos, parámetros anómalos, cambios de cuentas y consultas inusuales. Evitá guardar contraseñas, tokens o datos personales completos en los logs. Una alerta es un punto de investigación, no una prueba automática de compromiso.

CMS, plugins y frameworks

Mantené actualizado el CMS, los plugins, los temas, las bibliotecas y el motor de base de datos. Eliminá componentes abandonados y revisá especialmente extensiones que crean formularios, búsquedas, reportes o filtros personalizados.

Un firewall de aplicaciones puede detectar patrones conocidos y reducir intentos automatizados, pero no reemplaza la parametrización. Si una regla del WAF se desactiva para resolver un falso positivo, limitá la excepción a la ruta y regla necesarias; no deshabilites toda la protección sin análisis.

Lista de comprobación para desarrolladores

  1. Localizá todas las consultas y eliminá la concatenación de datos externos.
  2. Usá parámetros incluso en procesos internos, importaciones y tareas programadas.
  3. Mapeá identificadores dinámicos mediante listas permitidas.
  4. Probá cada rol y verificá que la cuenta de base de datos tenga permisos mínimos.
  5. Ocultá errores técnicos al público y protegé los registros.
  6. Incluí pruebas de seguridad cada vez que cambien filtros, búsquedas o reportes.

La misma entrada también puede provocar otros riesgos si se muestra sin tratamiento. Revisá la guía sobre qué es XSS y cómo prevenirlo y la de protección de formularios contra spam y abuso.

Qué hacer ante una posible intrusión

Preservá los logs antes de modificarlos, restringí temporalmente la función vulnerable y corregí el código. Revisá cuentas, privilegios, registros alterados, archivos del sitio, tareas programadas y actividad administrativa. Rotá las credenciales de base de datos y de la aplicación si pudieron quedar expuestas.

Restaurar una copia sin cerrar la vulnerabilidad permite que el problema se repita. Después de recuperar el servicio, verificá la integridad de los datos, aplicá actualizaciones, repetí las pruebas y documentá el origen. La combinación más efectiva es parametrización, validación, permisos mínimos, manejo seguro de errores y monitoreo continuo.