Java原生的序列化和反序列化
之前学过php
序列化与反序列化,以上就不赘述关于序列化与反序列化的一些概念问题了。感兴趣的师傅可以看看这篇文章:php反序列化 (symya.github.io)
进入正题。
Serializable 接口
基本使用
只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)
Serializable 接口是 Java 提供的序列化接口,它是一个空接口
Serializable 用来标识当前类可以被 ObjectOutputStream 序列化,以及被 ObjectInputStream 反序列化。
通过 ObjectOutputStream
将需要序列化数据写入到流中,因为Java IO
是一种装饰者模式,因此可以通过 ObjectOutStream
包装 FileOutStream
将数据写入到文件中或者包装 ByteArrayOutStream
将数据写入到内存中。同理,可以通过 ObjectInputStream
将数据从磁盘 FileInputStream
或者内存 ByteArrayInputStream
读取出来然后转化为指定的对象即可。
我们直接来看一个java
序列化与反序列化的demo
。
Person.java
文件
1 | import java.io.Serializable; |
serializationTest.java
文件
1 | import java.io.FileOutputStream; |
serialize
方法用于将传入的对象序列化并写入到指定的文件中。ObjectOutputStream
用于将对象的状态转换为字节流,并通过FileOutputStream
将这些字节写入到文件test.ser
中。
:在main
方法中,首先创建了一个Person
对象,然后打印出它的字符串表示(调用toString
方法),最后将这个对象序列化到文件中。
UnserializationTest.java
文件
1 | import java.io.FileOutputStream; |
unserilaize
方法用于从文件中读取序列化的对象,并将其反序列化为一个Java对象。ObjectInputStream
用于将字节流转换为Java对象。
在main
方法中,从test.ser
文件中读取了序列化的Person
对象,进行了类型转换后,打印出反序列化的对象(再次调用toString
方法)。
接口特点
- 序列化类的属性没有实现 Serializable 那么在序列化就会报错
- 在反序列化过程中,它的父类如果没有实现序列化接口,那么将需要提供无参构造函数来重新创建对象。
- 一个实现 Serializable 接口的子类也是可以被序列化的。
- 静态成员变量是不能被序列化
- 序列化是针对对象属性的,而静态成员变量是属于类的。
- transient 标识的对象成员变量不参与序列化
关于第五点,还是举上面的例子。我们把Person类中的name属性标识上transient
1 | private transient String name; |
再次运行序列化和反序列化的代码,得到结果
- Serializable 在序列化和反序列化过程中大量使用了反射,因此其过程会产生的大量的内存碎片
关于readObject和writeObject
jdk中默认提供,也可重写,开发中重写多是为了避免资源浪费,但引入了安全问题。原因是只要服务端反序列化数据,客户端传递类的readObject中的代码会自动执行。
可能可以利用的形式:
- 入口类参数中包含可控类,可控类调用其他危险函数的类,readObject时调用
- 构造函数/静态代码块等类加载时隐式执行。
关于第一种可利用的形式,我们还是看上面那个例子。在理想条件下:
Person.java文件
1 | import java.io.IOException; |
序列化与反序列化后就会发现,重写的readObject方法导致了命令执行。
条件:
- 继承或使用seriliable(必需要的)
- 入口类source –> map类,hashMap等
- 重写readObject()
- 参数类型宽泛 ,调用的常见的函数
- 最好是jdk自带的
- 调用链 gadget chain
- 相同名称 相同类型 不同的调用
- 找到一个执行类 sink (rce ssrf 写文件等等)
参考文章:
Drun1baby/JavaSecurityLearning: 记录一下 Java 安全学习历程,也算是半条学习路线了 (github.com)
java序列化与反序列化全讲解_反序列化会进无参构造吗-CSDN博客
Java反序列化漏洞专题-基础篇(21/09/05更新类加载部分)_哔哩哔哩_bilibili