Manejo inseguro de salidas
Descripción
Las salidas del LLM se pasan a sistemas posteriores o se renderizan sin validación. Esto genera vulnerabilidades de inyección cuando las salidas contienen código o comandos maliciosos.
Riesgo
Tratar las salidas del LLM como datos confiables permite ataques de inyección en sistemas posteriores. Las salidas pueden contener inyección SQL, XSS, inyección de comandos u otras cargas maliciosas que se ejecutan al ser procesadas por sistemas de backend o renderizadas en interfaces de usuario. Esto puede provocar filtraciones de datos, compromiso del sistema y escalamiento de privilegios.
Escenarios de ataque
Una función de búsqueda basada en LLM genera consultas SQL a partir de lenguaje natural. Un atacante diseña una entrada que hace que el LLM genere SQL malicioso que elimina tablas al ejecutarse.
Un sistema de generación de contenido renderiza las salidas del LLM directamente en HTML sin sanitización, lo que permite que el modelo inyecte JavaScript que roba tokens de sesión de otros usuarios.
Mitigaciones
Validación de salidas
Validar y sanitizar todas las salidas del LLM antes de usarlas. Tratar las salidas como entrada de usuario no confiable y aplicar los mismos controles de seguridad.
Interfaces parametrizadas
Utilizar consultas parametrizadas, sentencias preparadas y API seguras al pasar salidas del LLM a sistemas de backend. Nunca construir comandos o consultas mediante concatenación de cadenas.
Política de seguridad de contenido
Aplicar encabezados CSP y codificación de salida al renderizar contenido del LLM en aplicaciones web. Utilizar escapado sensible al contexto según el destino de la salida.
Ejecución con mínimo privilegio
Ejecutar los sistemas posteriores con los permisos mínimos requeridos. Limitar el impacto de los ataques de inyección exitosos mediante defensa en profundidad.
Ejemplos de código
# Incorrecto: Ejecución directa de la salida del LLM
consulta = llm.complete(f"Generar SQL para: {solicitud_usuario}")
bd.execute(consulta) # Riesgo de inyección SQL
# Correcto: Validar y usar consultas parametrizadas
import re
from typing import Optional
def validar_salida_sql(salida_llm: str) -> Optional[dict]:
# Analizar la salida estructurada, rechazar SQL libre
if not salida_llm.startswith('{'):
return None
analizado = json.loads(salida_llm)
operaciones_permitidas = ['SELECT', 'INSERT', 'UPDATE']
if analizado.get('operation') not in operaciones_permitidas:
return None
return analizado
salida_llm = llm.complete(f"Generar plan de consulta: {solicitud_usuario}")
plan_consulta = validar_salida_sql(salida_llm)
if plan_consulta:
# Usar ejecución parametrizada segura
bd.execute(
"SELECT * FROM products WHERE category = ?",
(plan_consulta['category'],)
)
Requisitos de evidencia
- Revisiones de código que muestren la validación de salidas antes del procesamiento posterior
- Uso de consultas parametrizadas y sentencias preparadas
- Codificación de salida e implementación de CSP para el renderizado web
- Informes de pruebas de seguridad que validen la resistencia a la inyección
- Documentación de los requisitos de seguridad para el manejo de salidas