java反序列化基础(二)

Java反序列化漏洞

产生的原因

只要服务端反序列化数据,客户端传递类的readObject中代码会自动执行,给予攻击者在服务器上运行代码的能力。

可能的形式

1.入口类的readObject直接调用危险方法。(在实际情况中这种很难存在,因为已知readObject一定会被执行的情况下再加入危险方法,这样的程序员一般会被拉去枪毙。)

2.入口类参数中包含可控类,该类有危险方法,readObject时调用。

3.入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject时调用。
比如类型定义为Object,调用equals/hashcode/toString

4.构造函数/静态代码块等类加载时隐式执行。

共同条件

继承Serializable(保证可以被序列化与反序列化)

入口类  [重写readObject(需要调用下一步的代码)  参数类型宽泛(可以往里面任意传)   最好jdk自带(可以通用)]  例如:Map对象

调用链  

执行类(rce SSRF 写文件)

示例代码

我们以入口类的readObject直接调用危险方法为例来实现一次反序列化攻击的流程。

先自定义一个可以被反序列化的类,并且重写readObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

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

public Person(String name, int age){
this.name = name;
this.age = age;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.defaultReadObject();
Runtime.getRuntime().exec("calc");
}
}

之后实例化并且将这个类序列化,保存在ser.bin文件中

1
2
3
4
5
6
7
8
9
import java.io.*;

public class SerializePerson {
public static void main(String[] args) throws IOException {
Person person = new Person("aa", 22);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(person);
}
}

读取ser.bin,反序列化,执行readObject,弹出计算器

1
2
3
4
5
6
7
8
import java.io.*;

public class unSerializePerson {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
Object o = ois.readObject();
}
}

成功执行
执行成功


java反序列化基础(二)
https://fliggyaa.github.io/2023/10/18/2023-10-18-java反序列化基础/
作者
fliggy
发布于
2023年10月18日
许可协议