java反序列化杂谈/1

反序列化杂谈

0x00 前言

看了些shiro环境因为重写了resolveClass的方法导致很多链无法利用后,终于搞清楚了原理。所以想搞清楚反序列化底层究竟是怎么回事。基础打牢对后面的反序列化的问题才会有更深刻的认实。

0x01 使用场景

抓取数据包的时候,很多数据是非常直观的,所以使用场景内对参数的敏感程度非常重要。

1
2
3
4
1、 http参数,cookie,sesion,存储方式可能是base64(rO0),压缩后的base64(H4sl),MII((Media Independent Interface(介质无关接口);或称为媒体独立接口?没遇到过)等
2、 Servlets HTTP,Sockets,Session管理器 包含的协议就包括JMX,RMI,JMS,JNDI等(\xac\xed)
3、 xml Xstream,XMLDecoder等(HTTP Body:Content-Type:application/xml)
4、 json(Jackson,fastjson) http请求中包含

0x02 readObject方法分析

在前面先贴一张readObject的执行流程图,这是一张weblogic的反序列化执行流程图。第一个readObject直接忽略,到下篇文weblogic再做讲解。

img

img

1
2
3
4
5
6
7
resolveClass:686, ObjectInputStream (java.io)
readNonProxyDesc:1868, ObjectInputStream (java.io)
readClassDesc:1751, ObjectInputStream (java.io)
readOrdinaryObject:2042, ObjectInputStream (java.io)
readObject0:1573, ObjectInputStream (java.io)
readObject:431, ObjectInputStream (java.io)
main:15, TestSerial (serial)

image-20211105103418851可以看到这里Class.forName不进行类的初始化,只是获得这个类对象。所以这里我们static代码块是不会被执行的。

接下来走出这个函数,走进这个函数,一看这个函数就是要初始化什么东西,我们再详细看看里面的参数的关键参数:

image-20211105103719835

image-20211105103809585

ObjectStreamClass Filed参数里面的Integer的age 和String类型的name;剩下的就是name和序列化的suid。
cl参数是一个class类,那关键的肯定是name参数和classloader,决定这个类是由哪个类加载器加载,这里可以很清楚的看到是应用类加载器。剩下的两个参数都是null。

image-20211105110714595

这个方法一执行完,我静态代码块里的计算机就跳出来了。

image-20211105110853066

就是里面的这句话。entry是个Object用来接收参数。

image-20211105111449805

image-20211105111437945

执行了一堆初始化,直到最后一句执行完才生成计算机。

image-20211105111629514

我觉得是这个类的实例在生成的时候,内部类cl也要去实例化,导致的static代码块的触发。

回到readOrdinaryObject方法,这里将这个类newInstance()了,但是静态代码块的方法在前面就执行了。这里的newInstance是调用ObjectStreamClass的newInstance

image-20211105110519183

image-20211105140554154

然后在这个方法把序列化的数据填充进去

image-20211105140656141

resolveClass这个方法究竟是做什么的?

将类的序列化描述符加工成该类的 Class 对象。

resolveClass和resolveProxyClass有什么区别?