序列化:内存信息被分成小块设置编号 ——>存到硬盘
反序列化:组装成对象恢复到内存中 <——硬盘保存Java对象的字节
条件
在Java类中,必须要实现java.io.ObjectOutputStream 和java.io.ObjectIutputStream来现实序列化反序列化的功能。一个类想要实现序列化和反序列化,必须要实现 java.io.Serializable 或java.io.Externalizable 接口
反序列化漏洞
如果被序列化的类重写了writeObject和readObject方法,Java就会委托这两个重写的方法来进行序列化和反序列化。正是因为这个特性才导致反序列化漏洞出现:在反序列化一个类时,如果这个类重写了readObject方法,程序将会调用这个重写的方法,如果重写的readObject方法存在恶意程序,将会对应用程序造成危害。
反序列化
先对某个对象进行反序列化,看一下重写readObject()触发反序列化漏洞
那么我们重写了readObject()就可以利用反序列化漏洞,原因是什么呢?
先看java.io.ObjectOutputStream#readObject()
readObject()方法调用readObject0()反序列化
readObject0()是以字节方式去读取
进入readOrdinaryObject()
先检查标记是否为Object 然后调用readClassDesc()获取类描述符
根据获取的内容判断类是否实现了Externalizable()接口,如果实现了该接口则调用readExternalData() 如果没有实现Externalizable(),则调用readSerialData()方法
在readSerialData()方法中,通过类描述符获取序列化对象的数据布局
进行判断是否重写了readObject()方法,如果重写了,就是用invokReadObject()调用对象里重写的readObject()方法
如果没有就执行默认的反序列化方法
至此,执行到invokReadObject()方法,就会调用重写的readObject()方法,如果重写的readObject()里边有危险函数那么这个危险函数就会执行。
文章如有错误或者不足之处,欢迎指正