Basic Java Deserialization (ObjectInputStream, readObject)

支持 HackTricks

在这篇文章中,将解释一个使用 java.io.Serializable 的示例。

Serializable

Java Serializable 接口(java.io.Serializable 是一个标记接口,您的类必须实现它才能被 序列化反序列化。Java 对象序列化(写入)是通过 ObjectOutputStream 完成的,反序列化(读取)是通过 ObjectInputStream 完成的。

让我们看一个 可序列化的类 Person 的示例。这个类 重写了 readObject 函数,因此当 这个类的任何对象反序列化 时,这个 函数 将会被 执行。 在这个示例中,类 Person 的 readObject 函数 调用了它的宠物的 eat() 函数,而狗的 eat() 函数(出于某种原因)调用了 calc.exe我们将看到如何序列化和反序列化一个 Person 对象以执行这个计算器:

以下示例来自 https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649

import java.io.Serializable;
import java.io.*;

public class TestDeserialization {
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream  and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
}

结论

正如您在这个非常基本的例子中所看到的,这里的“漏洞”出现是因为readObject函数在调用其他易受攻击的函数

支持 HackTricks

Last updated