OWASP: A05 2025 - Injection
¿Qué es Injection?
Una vulnerabilidad de Injection aparece cuando datos controlados por el usuario alcanzan un intérprete y consiguen modificar la estructura o el significado de una consulta, comando, expresión o documento que la aplicación pretendía ejecutar.
El intérprete puede ser una base de datos SQL o NoSQL, una shell del sistema operativo, un motor de plantillas, un navegador, LDAP, XPath u otro componente capaz de interpretar sintaxis.
El objetivo durante las pruebas no es únicamente provocar errores con caracteres especiales, sino determinar si una entrada controlada puede alterar la operación que ejecuta el backend o el navegador.
En este artículo analizamos las siguientes áreas:
SQL Injection
NoSQL Injection
OS Command Injection
Server-Side Template Injection (SSTI)
Cross-Site Scripting (XSS)
LDAP Injection
XPath Injection
SQL Injection
Una SQL Injection ocurre cuando datos controlados por el usuario se incorporan a una consulta SQL sin mantener una separación segura entre la consulta y sus valores.
Por ejemplo, una aplicación podría construir internamente una consulta como:
SELECT * FROM users WHERE username = '$username';
Si el valor recibido se concatena directamente, una entrada que contenga sintaxis SQL puede modificar la estructura de la consulta.
Durante una evaluación, busca parámetros utilizados para:
- Autenticación.
- Búsqueda y filtrado.
- Ordenación de resultados.
- Identificadores de objetos.
- Generación de informes.
- Consultas de APIs.
- Parámetros enviados mediante JSON, XML o formularios.
- Cookies, cabeceras HTTP u otros valores que puedan terminar almacenados o utilizados posteriormente.
No limites las pruebas a parámetros numéricos o a campos visibles en formularios.
Detección inicial
Una comprobación básica consiste en modificar un parámetro con caracteres que puedan afectar al parser SQL, por ejemplo:
'
"
\\
Si una entrada provoca una respuesta diferente, un error del motor de base de datos o un cambio consistente en el comportamiento, existe una señal que merece análisis.
Por ejemplo:
GET /product?id=15 HTTP/1.1
Host: target.com
puede compararse con:
GET /product?id=15' HTTP/1.1
Host: target.com
Presta atención a:
- Cambios en el código de estado.
- Diferencias en el tamaño o contenido de la respuesta.
- Errores SQL.
- Cambios en el número de resultados.
- Diferencias consistentes en tiempos de respuesta.
- Respuestas diferentes ante condiciones lógicamente verdaderas y falsas.
Un error 500 Internal Server Error no confirma por sí solo una SQL Injection. La aplicación puede fallar simplemente porque el valor recibido no cumple el formato esperado.
SQL Injection basada en condiciones booleanas
Cuando la aplicación no muestra errores SQL, puede ser posible determinar si una entrada modifica la consulta comparando condiciones que deberían producir resultados opuestos.
Por ejemplo, partiendo de:
GET /product?id=15 HTTP/1.1
pueden compararse entradas conceptualmente equivalentes a una condición verdadera y una falsa:
15 AND 1=1
15 AND 1=2
La sintaxis exacta depende del motor de base de datos y del contexto en el que se inserte el valor.
La señal relevante no es únicamente que las respuestas sean distintas, sino que las diferencias sean consistentes y explicables por el resultado lógico de la condición introducida.
SQL Injection basada en errores
Algunos motores devuelven mensajes suficientemente detallados como para identificar:
- El producto y versión aproximada de la base de datos.
- La consulta o una parte de ella.
- Nombres de tablas o columnas.
- Tipos de datos.
- Funciones utilizadas.
- La posición aproximada donde se produjo el error.
Por ejemplo, una respuesta que contenga:
You have an error in your SQL syntax
o:
Unclosed quotation mark after the character string
puede indicar que la entrada ha alcanzado un parser SQL.
No obstante, un mensaje de error únicamente confirma que se produjo un fallo relacionado con SQL. Debes comprobar si el usuario puede influir realmente en la estructura de la consulta.
UNION-based SQL Injection
Cuando los resultados de una consulta se muestran directamente en la respuesta, una cláusula UNION puede permitir combinar el resultado original con otra consulta.
Antes de intentar recuperar información, determina si el punto de inyección permite alterar la estructura de la sentencia y cuál es el número y tipo de columnas esperadas.
Por ejemplo, durante una validación controlada pueden utilizarse valores constantes:
UNION SELECT NULL,NULL
El uso de NULL resulta útil porque suele ser compatible con distintos tipos de columna y evita consultar información real mientras se determina la estructura de la respuesta.
Una vez demostrado que una consulta adicional puede incorporarse y que sus valores aparecen en la respuesta, normalmente no es necesario extraer grandes cantidades de información para confirmar el hallazgo.
Red Team OPSEC
Prioriza valores constantes, funciones inocuas y consultas mínimas para confirmar el control sobre la sentencia.
Evita enumerar bases de datos completas, volcar tablas o recuperar grandes cantidades de información cuando unas pocas evidencias sean suficientes para demostrar el impacto.
Blind SQL Injection
En una Blind SQL Injection la aplicación no devuelve directamente el resultado de la consulta ni errores útiles, pero el comportamiento puede variar dependiendo del resultado de una condición.
Las señales habituales son:
- Cambios en el contenido.
- Diferencias en el código HTTP.
- Diferencias en redirecciones.
- Presencia o ausencia de determinados elementos.
- Cambios reproducibles en tiempos de respuesta.
En las variantes basadas en tiempo, una función de demora controlada puede ayudar a determinar si una expresión SQL ha sido ejecutada.
La prueba debe repetirse y compararse con solicitudes de control, ya que la latencia de red, carga del servidor o mecanismos de protección pueden generar falsos positivos.
Red Team OPSEC
Las pruebas basadas en tiempo pueden consumir conexiones o workers del servidor. Utiliza demoras cortas y un número reducido de repeticiones.
No automatices extracciones carácter por carácter salvo que exista una necesidad concreta y esté dentro del alcance de la evaluación.
Second-order SQL Injection
En algunos casos, el valor vulnerable no se utiliza inmediatamente.
Por ejemplo, una aplicación puede almacenar un nombre, comentario u otro dato de forma aparentemente segura y utilizarlo posteriormente para construir otra consulta vulnerable.
Esto se conoce como Second-order SQL Injection.
Durante el análisis, considera también datos que:
- Se almacenan y se procesan posteriormente.
- Aparecen en paneles administrativos.
- Se utilizan para generar informes.
- Se transfieren entre distintos servicios.
- Son consumidos por tareas programadas o procesos internos.
La ausencia de un efecto inmediato no garantiza que el dato vaya a permanecer siempre en un contexto seguro.
ORMs y consultas dinámicas
El uso de un ORM no elimina automáticamente las vulnerabilidades de inyección.
Una aplicación puede seguir siendo vulnerable cuando:
- Construye HQL, JPQL u otra consulta mediante concatenación.
- Inserta fragmentos dinámicos como nombres de columnas u operadores.
- Permite al cliente definir estructuras de filtrado sin restricciones.
- Utiliza funciones equivalentes a consultas SQL sin parametrización.
El análisis debe centrarse en si el dato controlado permanece separado de la estructura de la consulta.
NoSQL Injection
Las bases de datos NoSQL utilizan modelos y lenguajes de consulta diferentes a SQL, pero pueden sufrir el mismo problema cuando la aplicación permite que una entrada controlada modifique la estructura de una operación.
Un escenario habitual aparece cuando una API espera valores simples:
{
"username": "sam",
"password": "secret"
}
pero acepta objetos o estructuras más complejas proporcionadas por el cliente.
Por ejemplo:
{
"username": {
"$ne": null
},
"password": {
"$ne": null
}
}
Dependiendo de cómo el backend construya la consulta, operadores recibidos desde el cliente podrían modificar su significado.
La existencia de campos con $, objetos anidados o tipos inesperados no confirma automáticamente una vulnerabilidad. Debes comprobar si el backend interpreta realmente esa estructura como parte de la consulta.
Pruebas de tipos y operadores
Durante las pruebas, modifica de forma controlada el tipo de los valores recibidos:
{
"id": "123"
}
por:
{
"id": {
"$ne": "123"
}
}
o utiliza arrays, booleanos, valores nulos u objetos cuando el endpoint esperaba un valor escalar.
Observa si:
- Cambia el conjunto de resultados.
- Se omiten controles de autenticación o filtrado.
- Aparecen errores procedentes del motor NoSQL.
- Se aceptan operadores que deberían ser construidos exclusivamente por el backend.
- El usuario obtiene acceso a registros adicionales.
La vulnerabilidad se confirma cuando el usuario puede modificar la lógica de la consulta, no simplemente cuando el backend acepta distintos tipos JSON.
Red Team OPSEC
Evita convertir una prueba de NoSQL Injection en una enumeración masiva de documentos.
Cuando sea posible, utiliza filtros que permitan demostrar el cambio de lógica con un conjunto mínimo y controlado de resultados.
OS Command Injection
Una OS Command Injection ocurre cuando una aplicación construye o ejecuta comandos del sistema operativo utilizando datos controlados por el usuario sin separar correctamente el comando de sus argumentos.
Busca funcionalidades que puedan invocar herramientas del sistema, por ejemplo:
- Diagnósticos de red.
- Resolución DNS.
- Conversión de archivos.
- Procesamiento de imágenes o vídeo.
- Compresión o descompresión.
- Generación de documentos.
- Operaciones con Git.
- Ejecución de herramientas administrativas.
- Integraciones que invoquen binarios externos.
Un ejemplo vulnerable conceptualmente podría construir:
nslookup <dominio_recibido>
Si el valor se entrega a una shell como parte de una cadena, caracteres especiales pueden cambiar el comando que termina ejecutándose.
Confirmación mediante una salida inocua
Cuando la respuesta muestra directamente la salida del proceso, empieza utilizando una operación inocua y fácilmente reconocible.
Por ejemplo, dependiendo del contexto y sistema operativo:
; echo INJECTION_TEST
o:
&& echo INJECTION_TEST
Si la cadena INJECTION_TEST aparece en una posición coherente con la salida del comando, existe una señal fuerte de ejecución.
La sintaxis depende de la shell, del sistema operativo y de cómo la aplicación invoque el proceso.
No asumas que todos los separadores funcionan de la misma manera ni que la aplicación utiliza necesariamente una shell.
Blind Command Injection
En ocasiones el comando se ejecuta pero su salida no se devuelve en la respuesta.
En ese caso puedes buscar efectos observables como:
- Diferencias consistentes en tiempo.
- Una petición HTTP hacia infraestructura controlada.
- Una consulta DNS hacia un dominio controlado.
- Cambios sobre un recurso de prueba expresamente preparado para la evaluación.
La confirmación fuera de banda suele ser preferible a intentar producir efectos sobre archivos o servicios reales del objetivo.
Red Team OPSEC
Utiliza comandos inocuos y reversibles para confirmar la ejecución. No es necesario crear persistencia, modificar usuarios, detener servicios o acceder a información sensible para demostrar una Command Injection.
En pruebas fuera de banda utiliza únicamente infraestructura bajo tu control y evita destinos de terceros.
Argument Injection
Aunque la aplicación evite una shell, puede continuar existiendo riesgo si el usuario controla argumentos proporcionados a un programa.
Por ejemplo, conceptualmente:
curl <valor_controlado>
puede resultar peligroso si el valor permite introducir opciones adicionales interpretadas por curl.
En este escenario el atacante no necesita ejecutar un segundo comando: puede alterar el comportamiento del programa que la aplicación ya había decidido ejecutar.
Durante la revisión, diferencia entre:
- Command Injection: el usuario consigue modificar o añadir comandos.
- Argument Injection: el comando permanece fijo, pero el usuario controla opciones o argumentos con capacidades no previstas.
Server-Side Template Injection (SSTI)
Una Server-Side Template Injection aparece cuando una entrada controlada por el usuario se interpreta como sintaxis de un motor de plantillas en el servidor.
El problema suele surgir cuando la aplicación construye dinámicamente una plantilla utilizando datos no confiables, en lugar de insertar esos datos como variables.
Por ejemplo, si una aplicación recibe:
Hola
y procesa directamente el contenido como plantilla, puede ser posible introducir expresiones propias del motor.
Detección
Empieza utilizando expresiones aritméticas simples que no produzcan efectos secundarios.
Ejemplos frecuentes según el motor pueden incluir:
{{7*7}}
${7*7}
<%= 7*7 %>
Si la respuesta contiene:
49
en lugar del texto literal introducido, puede indicar que el servidor está evaluando la expresión.
No utilices una única sintaxis para concluir que una aplicación no es vulnerable. Los delimitadores y expresiones dependen del motor de plantillas.
También debes distinguir una SSTI de una evaluación realizada en el navegador. La característica relevante es que la expresión sea procesada en el servidor.
Identificación del contexto
Una vez confirmada la evaluación, determina de forma limitada:
- Qué sintaxis reconoce.
- Si únicamente permite operaciones básicas.
- Qué objetos o variables expone el contexto.
- Si existe sandboxing.
- Si las funciones disponibles permiten acceder a capacidades más sensibles.
La gravedad puede variar desde una simple fuga de información hasta la ejecución de código, dependiendo del motor, su configuración y los objetos expuestos.
Red Team OPSEC
Para confirmar una SSTI suele ser suficiente demostrar la evaluación de una expresión inocua y, cuando resulte necesario, el acceso a un dato controlado del contexto.
Evita avanzar directamente hacia primitivas de ejecución de comandos, lectura de archivos o acceso a secretos si el hallazgo ya puede demostrarse de forma menos intrusiva.
Cross-Site Scripting (XSS)
Cross-Site Scripting ocurre cuando datos controlados por el usuario llegan a un contexto interpretado por el navegador sin la codificación o tratamiento adecuados, permitiendo introducir HTML o JavaScript que se ejecuta bajo el origen de la aplicación.
El análisis debe determinar en qué contexto aparece la entrada, ya que un mismo valor requiere tratamientos diferentes dependiendo de si se inserta en:
- Texto HTML.
- Un atributo HTML.
- JavaScript inline.
- Una URL.
- CSS.
- El DOM mediante JavaScript.
No consideres vulnerable un parámetro únicamente porque refleje caracteres especiales. La vulnerabilidad se confirma cuando el usuario puede romper el contexto previsto e introducir contenido ejecutable.
Reflected XSS
En un Reflected XSS la entrada enviada en una petición aparece inmediatamente en la respuesta.
Por ejemplo:
GET /search?q=INJECTION_TEST HTTP/1.1
Host: target.com
Comprueba dónde aparece INJECTION_TEST en el HTML devuelto.
Un primer paso seguro consiste en utilizar una marca única y caracteres que permitan entender el contexto:
xss-test-123'"<>
Después inspecciona el código fuente o DOM para determinar:
- Qué caracteres se codifican.
- Si el valor aparece dentro de una etiqueta.
- Si aparece dentro de un atributo.
- Si termina dentro de JavaScript.
- Si existen transformaciones entre la petición y la respuesta.
La selección del payload debe realizarse después de conocer ese contexto.
Stored XSS
En un Stored XSS el dato se guarda y se ejecuta cuando otro usuario o la misma víctima visita posteriormente una página que lo muestra.
Busca campos como:
- Nombres y perfiles.
- Comentarios.
- Tickets de soporte.
- Mensajes.
- Descripciones.
- Nombres de archivos.
- Datos importados.
- Campos que posteriormente consulta un administrador.
La prueba debe considerar quién visualizará el contenido almacenado. Un payload ejecutado únicamente en una cuenta de prueba propia demuestra un problema de tratamiento de salida, pero el impacto aumenta si el contenido es renderizado para otros usuarios o perfiles privilegiados.
Red Team OPSEC
En XSS almacenado utiliza contenido claramente identificable, inocuo y fácil de eliminar.
Evita payloads que capturen cookies, tokens, credenciales o información de usuarios reales. Para demostrar ejecución normalmente basta con un efecto local y no destructivo.
DOM-based XSS
En un DOM XSS la vulnerabilidad puede producirse completamente en el navegador cuando JavaScript toma datos de una fuente controlable y los introduce en un sink peligroso.
Algunas fuentes habituales incluyen:
location.href
location.search
location.hash
document.referrer
postMessage
localStorage
y algunos sinks relevantes son:
innerHTML
outerHTML
document.write
eval
setTimeout
setInterval
La presencia de una source y un sink no confirma por sí sola una vulnerabilidad. Debes comprobar si un dato controlado puede recorrer ese flujo y alcanzar el sink sin una transformación segura para el contexto.
CSP y otros controles
Una Content Security Policy puede reducir el impacto de determinadas variantes de XSS, pero no corrige el origen del problema.
Durante la evaluación separa:
- La existencia de una inyección HTML o JavaScript.
- La capacidad real de ejecutar script bajo las restricciones actuales del navegador.
- Las protecciones adicionales, como CSP, Trusted Types o sanitización.
Esto permite caracterizar correctamente un hallazgo incluso cuando una defensa adicional impide explotar una variante concreta.
LDAP Injection
LDAP Injection aparece cuando datos controlados por el usuario se incorporan a un filtro o consulta LDAP sin neutralizar correctamente los caracteres especiales del lenguaje.
Por ejemplo, una aplicación podría construir un filtro conceptualmente similar a:
(&(uid=<usuario>)(userPassword=<password>))
Si los valores se concatenan directamente, determinados caracteres pueden alterar la estructura lógica del filtro.
Busca especialmente:
- Formularios de autenticación.
- Búsquedas de usuarios.
- Directorios corporativos.
- Funciones de grupos y roles.
- Aplicaciones integradas con Active Directory u otros directorios LDAP.
Validación
Utiliza inicialmente valores que permitan detectar si el parser interpreta caracteres especiales, sin intentar enumerar el directorio.
Presta atención a:
- Errores LDAP.
- Cambios en autenticación.
- Diferencias en el número de resultados.
- Comportamiento distinto ante expresiones lógicas.
- Acceso a entradas que no deberían coincidir con el filtro original.
La vulnerabilidad se confirma cuando la entrada permite alterar la lógica de la consulta LDAP.
Red Team OPSEC
Evita utilizar la inyección para enumerar de forma masiva usuarios, grupos o atributos del directorio. Una modificación mínima del resultado esperado suele ser suficiente para demostrar el fallo.
XPath Injection
XPath Injection ocurre cuando una aplicación construye expresiones XPath utilizando datos controlados por el usuario.
Puede aparecer en aplicaciones que consultan documentos XML para realizar:
- Autenticación.
- Búsquedas.
- Filtrado de elementos.
- Selección de configuraciones.
- Procesamiento de documentos XML.
Un ejemplo conceptual podría utilizar:
/users/user[username='<usuario>' and password='<password>']
Si los valores se concatenan sin tratamiento adecuado, una entrada puede alterar la condición XPath.
Detección y validación
Como en SQL Injection, compara entradas que generen condiciones lógicamente diferentes y observa si el comportamiento de la aplicación cambia de forma consistente.
Presta atención a:
- Cambios en autenticación.
- Número de elementos devueltos.
- Errores del parser XPath.
- Diferencias reproducibles entre condiciones verdaderas y falsas.
El objetivo es determinar si el dato controlado forma parte de la expresión XPath y puede modificarla, no simplemente provocar un error de sintaxis.
Red Team OPSEC
Evita utilizar XPath Injection para recorrer documentos XML completos o extraer información sensible carácter por carácter cuando una prueba lógica mínima sea suficiente para confirmar el problema.
Consideraciones generales durante las pruebas
Las vulnerabilidades de Injection pueden aparecer en cualquier dato que termine alcanzando un intérprete. Por ello, no limites las pruebas a parámetros visibles de la URL.
Considera también:
- Parámetros GET y POST.
- JSON y XML.
- Multipart forms.
- Cookies.
- Cabeceras HTTP.
- Valores almacenados previamente.
- Datos importados desde archivos.
- WebSockets.
- Campos procedentes de servicios externos.
- Parámetros utilizados por tareas asíncronas.
La presencia de caracteres especiales, errores o respuestas diferentes constituye únicamente una señal inicial.
La vulnerabilidad se confirma cuando puede demostrarse que la entrada controlada modifica la estructura o semántica de una instrucción que posteriormente interpreta otro componente.
Durante la validación, intenta reducir cada prueba a la mínima evidencia necesaria: una condición booleana controlable, una expresión matemática evaluada, una salida inocua, un cambio de resultados o una ejecución de JavaScript no destructiva suelen aportar una evidencia más clara y reproducible que una explotación extensa.