Glosario
Qué es la inyección SQL (SQLi): cuando la entrada reescribe los comandos de tu base de datos
La inyección SQL (SQLi) ocurre cuando la entrada del usuario reescribe el significado de una consulta SQL, permitiendo leer, alterar o borrar datos. Cómo funciona y la defensa real: marcadores de posición y sentencias preparadas, además de ORMs.
«El texto que escribiste en un cuadro de búsqueda se convierte en 'parte de un comando' para la base de datos»: eso es la inyección SQL. Aquí tienes cómo funciona y cómo prevenirla de forma fiable (sin pasos de ataque).
Por qué ocurre (el mecanismo)
La causa raíz es construir SQL por concatenación de cadenas. Mezcla la entrada directamente en la sentencia y puede cruzar la «frontera del valor» y actuar como comando.
✗ Concatenación de cadenas (peligroso)
Entrada concatenada en la sentencia → la entrada puede leerse como parte del comando
✓ Marcadores de posición (seguro)
Valores pasados a las ranuras ? / $1 como datos → siempre siguen siendo valores
El daño es «todo lo que esa conexión a la BD pueda hacer». Si la BD interna es alcanzable, es una entrada clásica a fugas masivas, junto a RCE y SSRF.
Defensa
Usa marcadores de posición / sentencias preparadas (lo más importante)
No construyas SQL por concatenación. Pasa los valores mediante ? / parámetros con nombre como 'datos'. Esto por sí solo elimina casi toda la clase.
Apóyate en tu ORM / constructor de consultas
La mayoría de los ORMs usan marcadores de posición por defecto. Cuanto menos SQL en bruto escribas a mano, más seguro. Si debes escribir SQL en bruto, parametrízalo siempre.
Usuario de BD con privilegios mínimos
No concedas al usuario de BD de la aplicación derechos innecesarios (DROP, otras tablas, operaciones de administración). Aunque haya brecha, contén el daño.
Validación de entrada como complemento
Las comprobaciones de tipo/longitud/formato ayudan, pero no las conviertas en tu defensa principal: se asientan sobre los marcadores de posición.
La visión de este sitio: deja de construir SQL en bruto a mano para empezar
La SQLi existe desde siempre y no muere, porque es «cómodo» mezclar la entrada en la sentencia. La postura de este sitio es clara: nunca crees un lugar donde los valores se concatenen como cadenas dentro del SQL. Haz de los marcadores de posición o de un ORM el valor predeterminado y esta vulnerabilidad desaparece por diseño. No tomes el camino de «esforzarte más en el escape manual».
Un punto ciego: los marcadores de posición solo llevan 'valores'
Los marcadores de posición no son la panacea. Solo llevan valores, no la estructura de la consulta, como los nombres de tabla, los nombres de columna o la dirección del ORDER BY (asc/desc).
Cuando necesitas esos elementos dinámicos (por ejemplo, dejar que un usuario elija una «clave de ordenación» o «columna de filtro»), no metas la entrada en el SQL: selecciona el nombre real de una lista de permitidos predefinida. La «columna de ordenación» y la «columna de filtro» son los puntos ciegos clásicos donde la gente asume que los marcadores de posición los cubren.
Sigue leyendo
- Glosario: Qué es RCE · Qué es XSS
- Fundamentos: Fundamentos de seguridad
FAQ
Q¿Qué ocurre con la inyección SQL?
Un atacante cambia el significado de una consulta a la base de datos: leer datos que deberían estar ocultos, alterarlos o, en el peor caso, borrarlo todo o eludir la autenticación. Es una causa clásica de fugas masivas de datos.
Q¿Cuál es la defensa más fiable?
Pasar los valores mediante marcadores de posición (sentencias preparadas). No construyas SQL con concatenación de cadenas; pasa los valores como 'datos' por un canal separado para que la entrada nunca pueda leerse como comando. La mayoría de los ORMs lo hacen por defecto.
Q¿Basta con escapar la entrada?
El escape manual es propenso a errores y se desaconseja. Usa marcadores de posición. Además, da al usuario de la BD privilegios mínimos para reducir el radio de impacto si algo se cuela.