前言
在学习FastJson低版本漏洞时,机器不出网时,可以利用C3P0二次反序列化打内存马;之前就听说过Java二次反序化,但是一直不知道是啥;正好可以学习一波;
参考@Poria师傅
简单介绍
众所周知,com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
类乃万恶之源(类加载),很多利用链最后都是利用了它;如果此类在黑名单了该怎么办?
在某些情况下,就可以利用二次反序列化绕过黑名单;
简单介绍下二次反序列化,顾名思义,就是反序列化两次,其主要意义在于绕过黑名单的限制或不出网利用或者绕过一些loadClass()
不能够加载数组的问题;
利用方法
SignedObject
java.security下的一个类;
其构造方法会将第一个参数序列化,然后赋值给content
属性,SignedObject
的getObject
方法会将content
属性反序列化
利用方式如下:先构造一个恶意SignedObject
,然后调用它的getObject()
方法即可
1 | KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); |
利用思路:
- 谁的方法调用了
getObject
方法,然后一直往上跟readobject或者getter方法 - 谁的反射可控,直接进行反射调用
而Rome和CB中是可以调用某个类的getters方法的,
Rome
注意:我重写了resolveClass
方法,方便看在第一次反序列化时使用了那些类名
1 | import java.io.IOException; |
众所周知Rome有两条,既可以用HashCode也可以用equals;
我这里以HashCode为例:看着很长,其实就是在之前的对象上套了一层SignedObject而已
1 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; |
可以看到,成功绕过com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
;
CB
因为CB链也是可以调用某个类的getters方法的,所以也可以通过SignedObject.getObject()
来二次反序列化
1 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; |
Click1
因为Click1链也是可以调用某个类的getters方法的,所以也可以通过SignedObject.getObject()
来二次反序列化
1 | import java.io.*; |
RMIConnector
javax.management
下一个与远程 rmi 连接器的连接类
最终在javax.management.RMIConnector#findRMIServerJRMP
找到二次反序列化利用点;
给出二次反序列化的gadget
1 | javax.management.RMIConnector#connect |
到此,这个利用方法就通了,给出构造
1 | JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://"); |
利用思路:
- 谁的方法调用了
connect
方法并且传入的值可控 - 谁的反射可控,直接进行反射调用
师傅们给出的方法是通过InvokerTransformer
类,反射调用了connect方法;
(个人感觉有点鸡肋啊,InvokerTransformer这个类本身就很有可能在黑名单中,即使没有在黑名单中,为啥不直接反射调用SignedObject.getObject()
呢?,而且CC在3.2.2版本中 InvokerTransformer就用不了了)
CC6
给出CC6的示例
1 | import org.apache.commons.collections.Transformer; |
可以明显看出很鸡肋,感觉最大的作用是来绕过一些loadClass()
无法加载数组的情况;
列如:
反序列化默认是用的Class.forName
我这里重写resolveClass
,改成用URLClassLoader.loadClass()
去加载类
1 | import java.io.IOException; |
这就和shiro550漏洞很像,不能加载Transformer数组;网上有一种对应方法:可以将CC6之类的链改成可以不用Transformer数组;但是我这里甚至不能加载byte数组;只能用二次反序列化绕过
参考[TCTF 2021]buggyLoader; Java安全——JVM类加载器
WrapperConnectionPoolDataSource
com.mchange.v2.c3p0
下的一个类,所以需要c3p0依赖
1 | <dependency> |
最终在com.mchange.v2.ser.SerializableUtils#deserializeFromByteArray
找到二次反序列化利用点;
给出二次反序列化的gadget
1 | com.mchange.v2.c3p0.WrapperConnectionPoolDataSource#setUpPropertyListeners |
如图所示:
其中有一个判断语句,当其属性为userOverridesAsString
时,将调用parseUserOverridesAsString
方法
截取HexAsciiSerializedMap
之后的内容,进入到fromByteArray
最后进入到deserializeFromByteArray
中,进行二次反序列化
该链通常配合Fastjson
、Jackson
环境下不出网利用的打法;
1 | { |
可以打FastJson原生反序列化漏洞,而无需CC等依赖;参考@y4tacker师傅
C3P0
1 | import com.alibaba.fastjson.JSON; |
需要注意fastjon版本<=1.2.47;
总结
Java二次反序列化意义在于绕过黑名单的限制或不出网利用或者绕过一些loadClass()
不能够加载数组的问题;
由于RMIConnector过于鸡肋;常用的利用链是SignedObject
这条链;利用方式是看是否有利用链可以调用getters方法
WrapperConnectionPoolDataSource
这条链需要找到某条利用链可以调用setters方法,所以经常配合Fastjson
、Jackson环境下不出网利用