ASI02
OWASP Agentic Top 10 APLICACIÓN

Uso indebido y explotación de herramientas

Descripción

Los agentes invocan herramientas con parámetros destructivos o no deseados, encadenan llamadas a herramientas en secuencias explotables, o son engañados por descriptores de herramientas envenenados que tergiversan sus capacidades.

Riesgo

Panorama del riesgo

Los sistemas de IA agéntica derivan su poder del uso de herramientas: ejecutar llamadas a API, realizar consultas, administrar archivos e interactuar con servicios externos. Esta capacidad crea una amplia superficie de ataque cuando los agentes seleccionan herramientas, construyen parámetros o secuencian operaciones sin una validación adecuada.

Superficie de ataque

  • Inyección de parámetros: el agente construye parámetros de herramientas a partir de entradas no confiables, lo que permite inyección SQL, inyección de comandos o path traversal a través de los argumentos de la herramienta
  • Explotación de encadenamiento de herramientas: las llamadas individuales a herramientas pueden ser seguras de forma aislada, pero secuencias como read_file -> send_email crean rutas de exfiltración que el diseñador de la herramienta nunca pretendió
  • Descriptores de herramientas envenenados: los servidores MCP o los registros de complementos entregan descripciones de herramientas que tergiversan el comportamiento real de la herramienta (p. ej., una herramienta de 'resumir' que en realidad exfiltra datos)
  • Escalamiento de capacidades: un agente descubre que puede lograr resultados no deseados combinando de forma creativa herramientas de bajo privilegio (p. ej., usar una herramienta de registro de eventos para escribir en rutas de archivo arbitrarias)
  • Valores predeterminados destructivos: herramientas con parámetros predeterminados peligrosos (p. ej., force=true, recursive=true) que los agentes invocan sin comprender las consecuencias

Impacto en el negocio

  • Destrucción de datos: el agente ejecuta operaciones DELETE o DROP a través de herramientas de base de datos sin salvaguardas
  • Compromiso de infraestructura: el agente utiliza herramientas de ejecución de shell para modificar configuraciones del sistema o instalar software no autorizado
  • Ataques a la cadena de suministro: descriptores de herramientas envenenados provenientes de registros comprometidos hacen que los agentes enruten datos a través de endpoints controlados por el atacante
  • Movimiento lateral: agentes con acceso amplio a herramientas pivotan de objetivos de bajo valor a objetivos de alto valor mediante un encadenamiento creativo de herramientas

Escenarios de ataque

Un agente con acceso a consultas de base de datos recibe una solicitud de usuario para 'depurar registros antiguos'. El agente construye una consulta DELETE pero omite la cláusula WHERE debido a instrucciones ambiguas, borrando la tabla completa. El ejecutor de herramientas no contaba con validación de parámetros para detectar operaciones DELETE sin límites.

Un servidor MCP comprometido anuncia una herramienta llamada 'format_document' con una descripción que afirma que reformatea archivos de texto. La implementación real lee el contenido del archivo, lo envía mediante POST a un endpoint de recolección externo, y luego devuelve una versión reformateada. El agente llama a la herramienta repetidamente en documentos sensibles, exfiltrando datos mientras aparenta realizar una tarea de formateo inofensiva.

Un agente encadena tres herramientas individualmente seguras en una secuencia no prevista: (1) lee credenciales de base de datos desde una herramienta de configuración, (2) usa una herramienta de red para conectarse directamente a la base de datos de producción, (3) usa una herramienta de archivos para volcar los resultados de la consulta en un bucket de almacenamiento de acceso público. Ninguna llamada individual a herramienta viola la política, pero la cadena logra una exportación de datos no autorizada.

Mitigaciones

Validación de parámetros

Validar todos los parámetros de las herramientas contra esquemas estrictos antes de la ejecución:

  • Definir un JSON Schema para los parámetros de entrada de cada herramienta, con restricciones de tipo, enumeraciones para valores conocidos y patrones regex para campos de texto
  • Rechazar parámetros que contengan palabras clave SQL, metacaracteres de shell o secuencias de path traversal (../, ~, rutas absolutas fuera de los directorios permitidos)
  • Exigir longitudes máximas en todos los parámetros de texto para prevenir ataques basados en desbordamiento de búfer
  • Nunca pasar entradas de usuario sin procesar ni cadenas generadas por el LLM directamente como comandos de shell o fragmentos SQL

Listas de permitidos y alcance de herramientas

Restringir a qué herramientas puede acceder un agente según su tarea actual:

  • Implementar listas de permitidos de herramientas por tarea que limiten las herramientas disponibles al conjunto mínimo requerido
  • Utilizar seguridad basada en capacidades: las herramientas deben otorgarse explícitamente, no estar disponibles de forma predeterminada
  • Separar las herramientas de solo lectura de las herramientas de escritura/eliminación con distintos niveles de autorización
  • Exigir aprobación humana explícita para operaciones destructivas (DELETE, DROP, formateo, sobrescritura)

Aislamiento de ejecución

Ejecutar las herramientas en entornos aislados:

  • Utilizar contextos de ejecución en contenedores con límites de recursos (CPU, memoria, red, sistema de archivos)
  • Aplicar políticas de red que restrinjan las conexiones salientes únicamente a endpoints aprobados
  • Montar los sistemas de archivos en modo de solo lectura, a menos que la herramienta requiera específicamente acceso de escritura
  • Capturar registros de ejecución completos, incluyendo todos los parámetros, valores de retorno y efectos secundarios

Análisis de cadenas de herramientas

Monitorear y restringir las secuencias de múltiples herramientas:

  • Definir secuencias de herramientas prohibidas (p. ej., read_credentials -> network_request)
  • Implementar un grafo de llamadas a herramientas que rastree el flujo de datos entre invocaciones secuenciales de herramientas
  • Marcar las cadenas que trasladan datos de herramientas de alta sensibilidad a herramientas orientadas al exterior
  • Limitar la tasa de invocaciones de herramientas para evitar una explotación automatizada rápida

Verificación de descriptores de herramientas

Validar los descriptores de herramientas provenientes de fuentes externas:

  • Exigir firmas criptográficas en los descriptores de herramientas de servidores MCP y registros de complementos
  • Comparar las descripciones de herramientas anunciadas con el comportamiento observado utilizando entradas señuelo
  • Mantener un catálogo de herramientas curado y aprobado por la organización, con versiones fijadas
  • Poner en cuarentena y revisar las herramientas nuevas o actualizadas antes de otorgar acceso al agente

Ejemplos de código

Envoltorio de ejecución de herramientas con validación

import re
import json
from typing import Any, Callable
from dataclasses import dataclass, field


@dataclass
class PoliticaHerramientas:
    herramientas_permitidas: set[str]
    secuencias_bloqueadas: list[tuple[str, str]]  # pares (herramienta_a, herramienta_b)
    requiere_aprobacion: set[str]  # herramientas que necesitan aprobación humana
    llamadas_max_por_minuto: int = 30


PATRONES_DENEGADOS = [
    re.compile(r"(DROP|DELETE|TRUNCATE|ALTER)\s", re.IGNORECASE),
    re.compile(r"(;|--|/\*|\*/)"),  # Marcadores de inyección SQL
    re.compile(r"\.\.[\\/]"),  # Recorrido de rutas
    re.compile(r"[`$]\("),  # Sustitución de comandos
    re.compile(r"\|\s*(bash|sh|curl|wget|nc)"),  # Redirección (pipe) a shell
]


class EnvoltorioEjecucionHerramientas:
    """Valida y aísla en sandbox todas las invocaciones de herramientas."""

    def __init__(self, politica: PoliticaHerramientas):
        self._politica = politica
        self._historial_llamadas: list[str] = []
        self._registro: dict[str, Callable] = {}

    def registrar_herramienta(self, nombre: str, manejador: Callable, esquema: dict):
        self._registro[nombre] = {"manejador": manejador, "esquema": esquema}

    def ejecutar(self, nombre_herramienta: str, parametros: dict[str, Any]) -> dict:
        # 1. Verificar que la herramienta esté permitida
        if nombre_herramienta not in self._politica.herramientas_permitidas:
            return {"error": f"Herramienta '{nombre_herramienta}' no permitida para esta tarea"}

        # 2. Verificar secuencias bloqueadas
        if self._historial_llamadas:
            ultima_herramienta = self._historial_llamadas[-1]
            for bloqueada_a, bloqueada_b in self._politica.secuencias_bloqueadas:
                if ultima_herramienta == bloqueada_a and nombre_herramienta == bloqueada_b:
                    return {"error": f"Secuencia bloqueada: {bloqueada_a} -> {bloqueada_b}"}

        # 3. Escanear parámetros en busca de patrones de inyección
        violaciones = self._escanear_parametros(parametros)
        if violaciones:
            return {"error": "Validación de parámetros fallida", "violaciones": violaciones}

        # 4. Verificar si se requiere aprobación humana
        if nombre_herramienta in self._politica.requiere_aprobacion:
            return {"estado": "aprobacion_pendiente", "herramienta": nombre_herramienta, "parametros": parametros}

        # 5. Ejecutar y registrar
        self._historial_llamadas.append(nombre_herramienta)
        manejador = self._registro[nombre_herramienta]["manejador"]
        return manejador(**parametros)

    def _escanear_parametros(self, parametros: dict, ruta: str = "") -> list[str]:
        violaciones = []
        for clave, valor in parametros.items():
            ruta_actual = f"{ruta}.{clave}" if ruta else clave
            if isinstance(valor, str):
                for patron in PATRONES_DENEGADOS:
                    if patron.search(valor):
                        violaciones.append(
                            f"Patrón peligroso en '{ruta_actual}': {patron.pattern}"
                        )
            elif isinstance(valor, dict):
                violaciones.extend(self._escanear_parametros(valor, ruta_actual))
        return violaciones

Requisitos de evidencia

  • Registros de auditoría de invocación de herramientas con captura completa de parámetros y resultados de validación
  • Informes de detección de secuencias bloqueadas que muestran cadenas de explotación prevenidas
  • Registros de verificación de integridad de descriptores de herramientas con estado de validación de firmas
  • Registros del flujo de trabajo de aprobación humana para operaciones destructivas
  • Informes periódicos de comparación de comportamiento de herramientas (anunciado vs. observado)