白袍的小行星

Java安全基础——序列化与反序列化

字数统计: 446阅读时长: 1 min
2021/06/01 Share

Java的序列化机制和PHP有相似之处,也有许多不同。
两者都是将对象中的属性转换为某种格式的数据流,反序列化时再将其还原。
但PHP的序列化过程是固定的,也就是在开始转换之后开发者就无法去对其再进行操作了,这里指的是对开发者来说,调用serialize函数完全是一个原子操作,那些魔术方法只是在序列化或反序列化的前后进行一些操作,但无法影响正在进行中的序列化或反序列化过程。
而Java反序列化则不同,因为有readObjectwriteObject.这两个方法分别在反序列化和序列化时调用,开发者可以通过这两个方法写入其他数据到数据流中。

来写一个例子,一个Java对象必须实现java.io.Serializable接口才能被序列化:

public class Test implements java.io.Serializable{
public String name;

Test(String name){
this.name = name;
}

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject("This is a test");
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
System.out.println((String) in.readObject());
}

public static void main(String[] args) throws IOException {
Test test = new Test("adan0s");
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("test.out"));
obj.writeObject(test);
}
}

序列化过程中调用的是ObjectOutputStream类的writeObject方法,我们这里相当于重写了此方法,以达到往序列化数据流中添加其他数据的目的。
使用NickstaDB/SerializationDumper来看看test.out文件:
20210601151315MJBsL7
我们自己添加的数据在objectAnnotation位置,下面来尝试反序列化并输出这个字符串:

public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream obj = new ObjectInputStream(new FileInputStream("test.out"));
obj.readObject();
}

20210601151623bS9onC

主要参考了phith0n师傅的Java安全漫谈系列。

CATALOG