java反序列化漏洞详解

文章目录

  • 什么是反序列化漏洞?
  • 调用过程

什么是反序列化漏洞?

PHP 的反序列化和java 的反序列化是两种不同的类型,序列化和反序列化本身没有漏洞点只是为了实现数据的完整高效的传输。

PHP 反序列漏洞是由于类里面的魔术方法调用了某个函数,该危险函数又调用了别的函数最终执行到了危险函数的位置

JAVA反序列化漏洞是由于开发者重写了 readObject 方法,该readObject 方法方法调用了别的方法,最终执行到了例如 Transfrom 方法的危险方法

调用过程

序列化:
ObjectOutputstream–>writeObject()

反序列化:
ObjectInputstream–> readObject()

上面是java中序列化和反序列化的函数,在反序列化过程中,往往要进行重写readobject()函数,因为如果不进行重写readObject()函数,系统默认调用的是父类的反序列化函数,如果在反序列化过程中存在转义,将序列化后的字节序列转成base64编码,子类继承后默认调用父类的readObject()是无法识别的,只有重写readObject()函数,在其中加入一个还原字节序列的函数,才能成功反序列化,这就是重写readObject()函数的意义所在

漏洞点:重写readObject()会调用其他的函数,调用的函数还可能调用另一个函数,在这个链式调用的过程中就可能出现危险函数,能执行任意代码,这个危险函数人为可控,这就是java的反序列化漏洞。

下面代码定义了一个类person,并继承了Serializable(用implements继承,只有这样该类的对象才能进行序列化和反序列化),然后进行了readObject()函数的重写,重写中加入了一句

Runtime.getRuntime().exec("calc");

这句会在反序列化时打开计算器,这就是漏洞点

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;	//导入三个包(文件)

public class Person implements Serializable {
	public int age;
	public String name;

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        Runtime.getRuntime().exec("calc");
        // 默认的反序列化操作
        in.defaultReadObject();
    }
}

下面完整代码test是测试程序。其中自定义了两个函数serialize()和deserialize()做序列化和反序列化的操作,其中自定义函数中分别包含有writeObject()和 readObject()函数。

然后调用serialize()函数序列化并将结果存到EMT.bin文件中,其中p是新建的对象(p对象继承了person类的特征,所以能调用writeObject()和 readObject()函数):

 serialize(p,filePath:"EMT.bin");

再用deserialize()函数反序列化EMT.bin中的字节序列并输出:

System.out.println("反序列化结果:" + deserialize("EMT.bin"));
import java.io.*;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    Person p=new Person();
    p.age=18;
    p.name="EMT";

        serialize(p,filePath:"EMT.bin");


        System.out.println("反序列化结果:" + deserialize("EMT.bin"));
    }

    public static void serialize(Object obj, String filePath) throws IOException {
        try (FileOutputStream fileOut = new FileOutputStream(filePath);
             ObjectOutputStream objectOut = new ObjectOutputStream(fileOut)) {
            objectOut.writeObject(obj);
        }
    }

    public static Object deserialize(String filePath) throws IOException, ClassNotFoundException {
        try (FileInputStream fileIn = new FileInputStream(filePath);
             ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
            return objectIn.readObject();
        }
    }
}

你可能感兴趣的:(网络安全,java,python,开发语言)