Tema 5

5. A03: Injection y bases de SQL Injection, NoSQL Injection y Command Injection

La inyección ocurre cuando una aplicación mezcla datos controlados por el usuario con instrucciones que serán interpretadas por otro componente, como una base de datos, un intérprete o el sistema operativo. Cuando esa frontera se rompe, el atacante deja de enviar datos y empieza a influir en la lógica ejecutada por el servidor.

Objetivo Entender cómo los datos se convierten en instrucciones
Enfoque SQL, NoSQL, comandos y validación segura
Resultado Reconocer una de las clases de fallas más clásicas y peligrosas

5.1 Introducción

Las aplicaciones web necesitan recibir datos y usarlos para hacer cosas útiles: buscar registros, filtrar resultados, autenticar usuarios, guardar comentarios, ejecutar tareas internas, llamar a otros servicios o transformar archivos. El problema aparece cuando la aplicación toma esas entradas y las incorpora de forma insegura dentro de una instrucción que otro componente interpretará.

Ese patrón general se conoce como inyección. No se trata solo de SQL Injection, aunque esa sea la variante más famosa. La misma idea puede afectar motores NoSQL, sistemas operativos, expresiones dinámicas, plantillas, parsers y otros contextos donde el dato del usuario termina influyendo en una sintaxis ejecutable.

En OWASP Top 10, Injection sigue siendo una categoría central porque sus impactos pueden ser devastadores: lectura y modificación masiva de datos, bypass de autenticación, ejecución de comandos, acceso al sistema y compromiso total de la aplicación.

5.2 Qué es exactamente una inyección

Existe una vulnerabilidad de inyección cuando la aplicación incorpora entrada controlada por el usuario en una consulta, comando o expresión sin separar correctamente los datos de las instrucciones.

El núcleo del problema puede resumirse así:

  • La aplicación recibe entrada externa.
  • Construye dinámicamente una instrucción usando esa entrada.
  • Otro componente interpreta la cadena resultante.
  • El atacante logra alterar el significado original de la instrucción.
La inyección no consiste simplemente en "mandar texto raro". Consiste en lograr que el sistema interprete ese texto como parte del lenguaje de control que usa internamente.

5.3 Por qué es una categoría tan importante

Injection es especialmente crítica por varias razones:

  • Afecta componentes muy centrales, como bases de datos y comandos del sistema.
  • Puede comprometer confidencialidad, integridad y disponibilidad al mismo tiempo.
  • Suele permitir automatización y explotación masiva.
  • Aparece por errores comunes de desarrollo, especialmente concatenación insegura.
  • En algunos casos puede llevar desde una simple búsqueda hasta control total del servidor.

Por eso esta categoría no debe estudiarse como un conjunto de payloads, sino como una falla estructural de separación entre datos e instrucciones.

5.4 La raíz conceptual: mezclar datos con lógica

La mayoría de las inyecciones nacen del mismo error conceptual: construir instrucciones mediante concatenación de cadenas usando datos externos. Cuando eso ocurre, el sistema deja abierta la posibilidad de que el atacante "rompa" el contexto previsto y agregue significado propio.

Esto puede pasar en múltiples escenarios:

  • Consultas SQL generadas manualmente.
  • Filtros NoSQL armados con estructuras manipulables.
  • Comandos del sistema construidos a partir de parámetros.
  • Evaluaciones dinámicas o plantillas inseguras.

La defensa principal no es adivinar todos los payloads posibles, sino diseñar el sistema para que los datos nunca se conviertan en control del intérprete.

5.5 SQL Injection: la variante más conocida

SQL Injection ocurre cuando la aplicación construye consultas SQL de forma insegura incorporando directamente entrada del usuario. Si el atacante altera la estructura de la consulta, puede modificar su significado.

Las consecuencias pueden incluir:

  • Leer datos que no deberían ser visibles.
  • Evitar filtros o restricciones de autenticación.
  • Modificar o borrar registros.
  • Ejecutar operaciones administrativas sobre la base.
  • En algunos entornos, pivotear hacia el sistema operativo o servicios adyacentes.

SQL Injection es un caso clásico porque muchas aplicaciones históricamente construyeron consultas concatenando directamente parámetros como usuario, contraseña, búsqueda o identificadores.

5.6 Dónde suele aparecer SQL Injection

No se limita al formulario de login. Puede aparecer en cualquier punto donde la aplicación use entrada externa dentro de una consulta SQL.

  • Login y recuperación de cuenta.
  • Búsquedas y filtros avanzados.
  • Parámetros de ordenamiento o paginación.
  • Paneles administrativos.
  • Reportes exportables.
  • APIs que consultan por identificadores o criterios dinámicos.

A veces la consulta vulnerable no es evidente porque está varios pasos detrás del formulario que el usuario ve en pantalla.

5.7 Qué puede lograr un atacante con SQL Injection

Objetivo del atacante Impacto típico
Bypass de autenticación Ingreso sin credenciales válidas
Lectura de datos Exposición de usuarios, contraseñas, pedidos, documentos
Alteración de información Cambios no autorizados en cuentas, saldos o configuraciones
Borrado o corrupción Pérdida de integridad o disponibilidad
Escalada técnica Mayor control sobre la base o sobre el entorno

El alcance real depende de los permisos que la aplicación tenga sobre la base de datos y de cómo esté segmentado el entorno.

5.8 SQL Injection y bypass de autenticación

Uno de los escenarios más conocidos es el bypass de autenticación. Si la aplicación arma una consulta SQL insegura con el usuario y la contraseña, el atacante puede alterar la lógica del where para que la consulta devuelva un resultado válido sin necesidad de conocer credenciales reales.

Lo importante aquí no es memorizar cadenas concretas, sino entender la lógica: cuando el servidor le permite al usuario alterar la condición de autenticación, el problema no está en la contraseña, sino en cómo se construyó la consulta.

5.9 SQL Injection ciega

No siempre la aplicación devuelve errores visibles o resultados completos. A veces la inyección sigue existiendo, pero el atacante debe inferir información a partir del comportamiento del sistema. A esto se lo suele llamar inyección ciega.

Algunas pistas indirectas pueden ser:

  • Cambios sutiles en el contenido de la respuesta.
  • Diferencias entre verdadero y falso en condiciones manipuladas.
  • Demoras temporales inducidas.
  • Errores parciales o inconsistencias en el flujo.

Este punto es importante porque muestra que ocultar mensajes de error ayuda, pero no elimina la vulnerabilidad si la consulta sigue siendo manipulable.

5.10 NoSQL Injection

Cuando las aplicaciones usan bases de datos NoSQL, el problema de inyección no desaparece. Solo cambia la sintaxis y el contexto. En muchos sistemas NoSQL, los filtros y consultas se construyen con objetos, expresiones o estructuras JSON que también pueden verse alteradas si la aplicación no valida correctamente la entrada.

NoSQL Injection puede permitir:

  • Modificar condiciones de búsqueda.
  • Bypass de autenticación.
  • Acceder a documentos no previstos.
  • Abusar de operadores especiales del motor.

El error conceptual sigue siendo el mismo: permitir que los datos del usuario entren en el lenguaje de consulta sin control suficiente.

5.11 Por qué algunos equipos subestiman NoSQL Injection

Existe un mito común: "como no usamos SQL, entonces no tenemos SQL Injection y ya está". Eso es una simplificación peligrosa. El riesgo de inyección no depende del nombre del motor, sino de cómo la aplicación construye e interpreta consultas o filtros.

Si un sistema toma estructuras controladas por el cliente y las usa como parte de la consulta sin validación estricta, sigue existiendo una superficie de manipulación.

5.12 Command Injection

Command Injection ocurre cuando la aplicación usa entrada del usuario para construir comandos que serán ejecutados por el sistema operativo o por una shell. Si el atacante logra alterar ese comando, puede influir directamente en la ejecución del servidor.

Este tipo de inyección suele ser muy grave porque puede pasar rápidamente del plano de aplicación al plano del host subyacente.

Ejemplos conceptuales donde puede aparecer:

  • Funciones que llaman utilidades del sistema para procesar archivos.
  • Diagnósticos de red o administración remota mal implementados.
  • Scripts que reciben nombres de archivo, rutas o parámetros sin saneamiento adecuado.
  • Tareas internas expuestas a usuarios privilegiados pero mal validadas.

5.13 Impacto de Command Injection

Cuando un atacante logra alterar comandos del sistema, el impacto puede escalar con rapidez.

  • Lectura de archivos sensibles del servidor.
  • Ejecución de programas no previstos.
  • Manipulación de archivos o configuraciones.
  • Pivoting hacia otros sistemas.
  • Compromiso total del host si los privilegios del proceso son altos.
Command Injection es especialmente peligrosa porque acerca mucho la explotación de una app web al control directo del sistema operativo.

5.14 Inyección no significa solo base de datos

Aunque el curso aquí se concentra en SQL, NoSQL y comandos, conviene fijar una idea más general: cualquier intérprete puede convertirse en superficie de inyección si recibe entradas no confiables como parte de su lenguaje.

Por eso el pensamiento defensivo debe ser amplio. Siempre que una aplicación genere dinámicamente consultas, expresiones, plantillas o comandos usando entrada externa, hay que preguntarse si el dato puede cambiar la sintaxis ejecutada.

5.15 La validación ayuda, pero no reemplaza la separación segura

Validar entradas es importante, pero no debe presentarse como única defensa. Un filtro incompleto puede ser bypassado, especialmente cuando se intenta bloquear caracteres o patrones peligrosos manualmente.

Las defensas más robustas son aquellas que evitan estructuralmente la mezcla insegura entre datos e instrucciones, por ejemplo usando consultas parametrizadas o APIs seguras del framework.

La validación sigue siendo valiosa para:

  • Restringir formatos esperados.
  • Normalizar entradas.
  • Reducir superficie de abuso.
  • Hacer más fácil razonar sobre casos válidos.

5.16 Concatenación insegura: el patrón a evitar

La concatenación de cadenas con datos del usuario dentro de consultas o comandos es uno de los patrones más peligrosos y repetidos en software vulnerable. Aunque resulte rápida de programar, crea una frontera insegura donde el dato puede convertirse en control.

Este patrón debe levantar una alarma inmediata en revisiones de código, especialmente si involucra:

  • Consultas SQL armadas manualmente.
  • Filtros complejos generados desde parámetros.
  • Comandos shell con variables externas.
  • Rutas, nombres de archivo o flags dinámicos sin control fuerte.

5.17 Señales que pueden sugerir una inyección

Durante una revisión o prueba, algunos indicios justifican análisis más profundo:

  • Errores del motor de base de datos visibles en pantalla.
  • Diferencias notorias al modificar caracteres especiales en entradas.
  • Consultas flexibles construidas a partir de muchos filtros dinámicos.
  • Procesamiento de archivos o comandos del sistema desde la web.
  • Uso intensivo de ensamblado manual de cadenas en código backend.
  • Bypasses extraños en login, búsqueda o filtros.

5.18 Causas comunes

  • Concatenar directamente entrada del usuario en consultas o comandos.
  • Confiar en filtrado ad hoc en lugar de APIs seguras.
  • No definir listas blancas para parámetros estructurales como ordenamiento o nombres permitidos.
  • Usar privilegios excesivos en la cuenta de base de datos de la aplicación.
  • Exponer funcionalidades internas que ejecutan tareas del sistema.
  • Desconocer cómo el framework o el motor interpreta ciertos operadores.

5.19 Mitigación principal: consultas parametrizadas

En el caso de SQL, la defensa más importante consiste en usar consultas parametrizadas o sentencias preparadas. La idea es que la estructura de la consulta y los datos se transmitan por canales diferenciados, de modo que el motor no reinterprete la entrada del usuario como parte del lenguaje SQL.

Esta separación es mucho más robusta que intentar escapar manualmente caracteres o bloquear cadenas peligrosas.

5.20 Mitigación en NoSQL y otros contextos

En motores NoSQL y otros intérpretes, el principio es similar: construir consultas y filtros mediante APIs seguras, validando fuertemente la estructura esperada y restringiendo operadores o campos permitidos.

En la práctica esto implica:

  • No aceptar objetos arbitrarios del cliente como si fueran filtros completos.
  • Definir explícitamente qué campos pueden filtrarse.
  • Limitar operadores y tipos aceptados.
  • Evitar evaluación dinámica de expresiones o plantillas no confiables.

5.21 Mitigación en Command Injection

La mejor defensa contra Command Injection es evitar invocar la shell o comandos del sistema cuando existe una alternativa segura dentro del lenguaje o framework. Si no hay otra opción, deben separarse claramente argumentos, restringirse valores y minimizar privilegios del proceso.

Buenas prácticas:

  • Preferir bibliotecas nativas antes que comandos del sistema.
  • No construir comandos concatenando texto de usuario.
  • Validar con listas blancas estrictas los argumentos permitidos.
  • Ejecutar procesos con el menor privilegio posible.
  • Aislar servicios que necesariamente deban interactuar con el sistema.

5.22 El principio de mínimo privilegio también importa aquí

Aunque exista una inyección, el impacto puede reducirse si la aplicación y sus componentes operan con privilegios limitados. Esto no corrige la vulnerabilidad, pero puede contener daño.

Ejemplos:

  • La cuenta de base de datos no debería poder hacer más de lo necesario.
  • El proceso web no debería ejecutarse con privilegios elevados.
  • Los servicios auxiliares deberían estar segmentados y aislados.

5.23 Errores frecuentes en la remediación

  • Agregar filtros superficiales de caracteres y creer que el problema está resuelto.
  • Escapar manualmente entradas en algunos lugares y olvidarlo en otros.
  • Corregir solo el login y dejar búsquedas, reportes o APIs vulnerables.
  • Ignorar cuentas de base de datos con permisos excesivos.
  • Asumir que usar ORM elimina automáticamente toda posibilidad de inyección.
  • Creer que no hay riesgo porque la aplicación no muestra errores.
La remediación real de una inyección no consiste en bloquear una cadena concreta. Consiste en cambiar la forma en que la aplicación construye e interpreta instrucciones.

5.24 Relación con otras vulnerabilidades

Injection puede combinarse con muchas otras categorías del curso:

  • Con Broken Access Control, si la inyección permite acceder a datos o funciones de otros usuarios.
  • Con Cryptographic Failures, si se exfiltran secretos, hashes o claves.
  • Con Vulnerable Components, si librerías inseguras facilitan interpretación riesgosa.
  • Con Logging Failures, si la explotación no queda registrada ni detectada.

Esto hace que una sola inyección pueda convertirse en puerta de entrada para compromisos mucho más amplios.

5.25 Qué debes recordar de este tema

  • La inyección ocurre cuando la entrada del usuario altera la sintaxis de una instrucción interpretada por otro componente.
  • SQL Injection, NoSQL Injection y Command Injection comparten la misma raíz conceptual.
  • El problema central es mezclar datos con lógica mediante construcción insegura de instrucciones.
  • Ocultar errores no elimina una inyección si la consulta o comando sigue siendo manipulable.
  • Las consultas parametrizadas y APIs seguras son defensas clave.
  • La validación ayuda, pero no sustituye la separación correcta entre datos e instrucciones.
  • El mínimo privilegio reduce impacto si una explotación llega a producirse.

5.26 Conclusión

Injection sigue siendo una de las categorías más representativas de la seguridad web porque muestra con claridad un principio esencial: cuando una aplicación deja que datos externos controlen la lógica interna de un intérprete, el atacante gana capacidad real de manipulación sobre el sistema.

En el próximo tema estudiaremos A04: Insecure Design, una categoría que va más allá de errores puntuales de implementación y nos obliga a pensar en cómo una aplicación puede ser insegura desde su propia arquitectura y lógica de negocio.