Prevención de inyección SQL en aplicaciones web modernas

Security2026-09-12TryQuickToolBox

La inyección SQL sigue siendo una de las vulnerabilidades más críticas en aplicaciones web. Los atacantes la explotan para robar datos, eludir la autenticación e incluso ejecutar comandos del sistema. Si tu aplicación construye consultas SQL concatenando la entrada del usuario, estás en riesgo. Este artículo explica cómo funciona la inyección SQL y proporciona pasos prácticos para prevenirla en aplicaciones web modernas.

Cómo ocurre la inyección SQL

La inyección SQL ocurre cuando datos no confiables se interpretan como parte de un comando SQL. Por ejemplo, considera un formulario de inicio de sesión que verifica credenciales con esta consulta:

SELECT * FROM users WHERE username = '$username' AND password = '$password';

Si un atacante ingresa ' OR '1'='1 como nombre de usuario y cualquier contraseña, la consulta se convierte en:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'anything';

Esto devuelve todos los usuarios, eludiendo la autenticación. Técnicas similares pueden extraer datos, modificar registros o eliminar tablas.

1. Usa consultas preparadas (consultas parametrizadas)

Las consultas preparadas separan el código SQL de los datos. La base de datos recibe primero la estructura de la consulta y luego los parámetros, por lo que la entrada del usuario nunca se trata como código SQL. Esta es la defensa más efectiva.

Ejemplo en PHP con PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $userInput]);
$user = $stmt->fetch();

Ejemplo en Java con JDBC:

String sql = "SELECT * FROM users WHERE email = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, userInput);
ResultSet rs = stmt.executeQuery();

Usa siempre consultas parametrizadas para todos los datos proporcionados por el usuario, incluidos campos de búsqueda, filtros y parámetros de ordenación.

2. Valida y sanea la entrada

Aunque las consultas preparadas son primordiales, la validación de entrada añade defensa en profundidad. Valida que la entrada coincida con los patrones esperados (por ejemplo, formato de correo electrónico, ID numérico) y rechaza cualquier cosa inesperada. Por ejemplo, si un ID debe ser un entero, conviértelo a int en tu código. Evita incluir en listas negras caracteres como las comillas: los atacantes pueden eludir dichos filtros.

3. Usa un ORM de forma segura

Los ORM como Hibernate, Entity Framework y Sequelize normalmente usan consultas parametrizadas de forma predeterminada. Sin embargo, a menudo permiten fragmentos de SQL sin procesar. Ten cuidado con los métodos que aceptan cadenas sin procesar:

Consulta siempre la documentación de tu ORM para construir consultas de forma segura.

4. Escapa los datos si las consultas preparadas son imposibles

En casos excepcionales en los que debas construir SQL dinámico (por ejemplo, nombres de tablas dinámicos), usa la función de escape de tu controlador de base de datos. Para MySQL, mysqli_real_escape_string() escapa caracteres especiales. Pero recuerda: el escape no es tan robusto como las consultas preparadas y debe ser el último recurso.

5. Aplica el principio de mínimo privilegio a las cuentas de base de datos

No te conectes a la base de datos como root ni con un usuario que tenga todos los privilegios. Crea un usuario de base de datos dedicado para tu aplicación con solo los permisos necesarios (SELECT, INSERT, UPDATE, DELETE en tablas específicas). Esto limita el daño si ocurre una inyección.

6. Usa un firewall de aplicaciones web (WAF)

Un WAF puede detectar y bloquear patrones comunes de inyección SQL. Aunque no sustituye una codificación segura, proporciona una capa adicional. Muchos proveedores de la nube ofrecen WAF gestionados fáciles de habilitar.

7. Pruebas de seguridad regulares

Prueba tu aplicación en busca de vulnerabilidades de inyección SQL usando escáneres automatizados o pruebas de penetración manuales. Herramientas como SQLMap pueden ayudar a identificar problemas. Integra las pruebas de seguridad en tu pipeline de CI/CD para detectar regresiones a tiempo.

Comparación de técnicas de prevención

Técnica Eficacia Facilidad de implementación
Consultas preparadas Alta Fácil (integrada en la mayoría de los controladores)
Validación de entrada Media Moderada
Uso seguro de ORM Alta Fácil si se conoce
Escapado Media Fácil pero propenso a errores
Mínimo privilegio Media Fácil
WAF Baja a Media Fácil (gestionado)

Preguntas frecuentes

¿Cuál es la forma más efectiva de prevenir la inyección SQL?

Usar consultas preparadas con consultas parametrizadas es el método más efectivo. Garantiza que la entrada del usuario nunca se interprete como código SQL.

¿Puede la validación de entrada por sí sola prevenir la inyección SQL?

No. La validación de entrada es una buena medida de defensa en profundidad, pero no debe ser lo único en lo que confíes. Los atacantes a veces pueden eludir las reglas de validación, así que usa siempre consultas preparadas como defensa principal.

¿Están los ORM automáticamente a salvo de la inyección SQL?

Los ORM son generalmente seguros cuando se usan correctamente, pero a menudo permiten consultas SQL sin procesar que pueden ser vulnerables si concatenas la entrada del usuario. Usa siempre consultas parametrizadas incluso dentro de los métodos del ORM.

Para mayor seguridad, considera usar un formateador JSON para inspeccionar y validar respuestas de API de forma segura sin ejecutar código malicioso.