ma4ter

Index | Photo | About | Friends | Archives

Java安全学习(序列化和反序列化)

Java 序列化是指把 Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化,将Java对象转为字节序列。

Java 反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化。
String、Integer、数组、Object对象等Java内置的数据类型均可实现序列化,自己写的类只要实现了Serializable接口即可实现序列化和反序列化。



import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class vultest{
    public static void main(String[] args) throws Exception{
    ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("person.dat"));
    objectOutputStream.writeObject(new Person("zhangsan",20));
    objectOutputStream.flush();
    objectOutputStream.close();
    }
}
class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

Java安全学习(序列化和反序列化)

这段代码将一个我自己设计的类person类序列化存储到了一个文件person.dat里面

值得注意的是 java的序列化与反序列化和php的有所不同

php的序列化是将其序列化成一个字符串 而java是将一个对象从内存中序列化到一个文件中存储

我们都知道在php中有各种魔术方法__destruct __toString等等 在一定的条件下就会自动去调用这些魔术方法

但是在java中没有这些 只有readobject和writeobject 什么意思呢 也就是说 我们将一个对象序列化成文件的时候会自动调用writeobject方法 在将一个文件恢复成一个对象的时候会自动调用readobject

我们可以下面演示一下

在person类中自己写一个writeobject这个方法

    private void writeObject(ObjectOutputStream objectOutputStream) throws Exception{
        objectOutputStream.defaultWriteObject();
        Runtime.getRuntime().exec("calc");
    }

Java安全学习(序列化和反序列化)

这样既实现了序列化过程又执行了用户自己的一些代码 相当于php中的__sleep方法 而反序列化则相当于__wakeup方法

注意我们在写这一个方法的时候需要有形参为ObjectOutputStream类型的对象且可见性修辞为private才能正常的访问到这个方法 需要实现默认的也就是 defaultWriteObject方法

反序列化也同理

Java安全学习(序列化和反序列化)

java中的序列化与反序列化也就这一点 但是真正的分析漏洞还在后面 因为程序员不会傻逼到把命令执行写在这两个方法中

借用y4er大佬博客中的一段话就是

但是你肯定会问,真正开发的时候谁会这么写啊,这不是故意写bug吗?确实,开发人员不会这么写,但是在重写 readObject()方法时会写一些正常的操作,我们这个时候就要提到反射了,关于更多java反序列化的问题请移步 深入分析Java的序列化与反序列化

在java中,反序列化很大部分是通过反射来构造pop链。