Basiese Java Deserialisering met ObjectInputStream readObject

Reading time: 7 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

In hierdie POST gaan 'n voorbeeld verduidelik word wat java.io.Serializable gebruik en waarom die oorskrywing van readObject() uiters gevaarlik kan wees as die inkomende stroom deur 'n aanvaller beheer word.

Serializable

Die Java Serializable-koppelvlak (java.io.Serializable) is 'n merk-koppelvlak wat jou klasse moet implementeer as hulle geserialiseer en gedeserialiseer moet word. Java objekserialisering (skryf) word gedoen met die ObjectOutputStream en deserialisering (lees) word gedoen met die ObjectInputStream.

Herinnering: Watter metodes word implisiet tydens deserialisering aangeroep?

  1. readObject() – klas-spesifieke leeslogika (as geïmplementeer en privaat).
  2. readResolve() – kan die gedeserialiseerde objek met 'n ander een vervang.
  3. validateObject() – via ObjectInputValidation terugroepe.
  4. readExternal() – vir klasse wat Externalizable implementeer.
  5. Konstruktors word nie uitgevoer nie – daarom is gadgetkettings uitsluitlik afhanklik van die vorige terugroepe.

Enige metode in daardie ketting wat eindig met die aanroep van aanvaller-beheerde data (opdraguitvoering, JNDI soektogte, refleksie, ens.) verander die deserialisering roetine in 'n RCE gadget.

Kom ons kyk na 'n voorbeeld met 'n klas Persoon wat serialiseerbaar is. Hierdie klas oorskry die readObject funksie, so wanneer enige objek van hierdie klas gedeserialiseer word, gaan hierdie funksie uitgevoer word.
In die voorbeeld roep die readObject funksie van die klas Persoon die funksie eat() van sy troeteldier aan en die funksie eat() van 'n Hond (om een of ander rede) roep 'n calc.exe aan. Ons gaan kyk hoe om 'n Persoon objek te serialiseer en te deserialiseer om hierdie sakrekenaar uit te voer:

Die volgende voorbeeld is van https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649

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

Gevolgtrekking (klassieke scenario)

Soos jy in hierdie baie basiese voorbeeld kan sien, verskyn die “kwesbaarheid” hier omdat die readObject() metode ander aanvaller-beheerde kode aanroep. In werklike wêreld gadget kettings kan duisende klasse wat in eksterne biblioteke (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, ens.) bevat is, misbruik word – die aanvaller het net een bereikbare gadget nodig om kode-uitvoering te verkry.


2023-2025: Wat is nuut in Java deserialisering aanvalle?

  • 2023 – CVE-2023-34040: Spring-Kafka deserialisering van fout-record koppe wanneer checkDeserExWhen* vlae geaktiveer is, het arbitrêre gadgetkonstruksie vanuit aanvaller-gepubliseerde onderwerpe toegelaat. Reggestel in 3.0.10 / 2.9.11. ¹
  • 2023 – CVE-2023-36480: Aerospike Java kliënt vertroude-bediener aanname gebroke – kwaadwillige bediener antwoorde het serialiseerde payloads bevat wat deur die kliënt gedeserialiseer is → RCE. ²
  • 2023 – CVE-2023-25581: pac4j-core gebruikersprofiel attribuut parsing het {#sb64}-geprefikseerde Base64 blobs aanvaar en dit gedeserialiseer ten spyte van 'n RestrictedObjectInputStream. Opgradeer ≥ 4.0.0.
  • 2023 – CVE-2023-4528: JSCAPE MFT Bestuurderdiens (poort 10880) het XML-gecodeerde Java-objekte aanvaar wat gelei het tot RCE as root/SYSTEM.
  • 2024 – Meerdere nuwe gadget kettings is by ysoserial-plus(mod) gevoeg, insluitend Hibernate5, TomcatEmbed, en SnakeYAML 2.x klasse wat sommige ou filters omseil.

Moderne versagtings wat jy moet implementeer

  1. JEP 290 / Serialisering Filtrering (Java 9+) Voeg 'n toelaat-lis of ontken-lis van klasse by:
bash
# Aanvaar slegs jou DTO's en java.base, verwerp alles anders
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"

Programmatiese voorbeeld:

java
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
  1. JEP 415 (Java 17+) Konteks-Spesifieke Filter Fabrieke – gebruik 'n BinaryOperator<ObjectInputFilter> om verskillende filters per uitvoeringskonteks toe te pas (bv. per RMI oproep, per boodskapqueue verbruiker).
  2. Moet nie rou ObjectInputStream oor die draad blootstel nie – verkies JSON/Binary kodering sonder kode-uitvoering semantiek (Jackson na deaktivering van DefaultTyping, Protobuf, Avro, ens.).
  3. Verdediging-in-diepte beperkings – Stel maksimum array lengte, diepte, verwysings in:
bash
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
  1. Deurlopende gadget skandering – hardloop gereedskap soos gadget-inspector of serialpwn-cli in jou CI om die bou te laat misluk as 'n gevaarlike gadget bereikbaar word.

Opgedateerde gereedskap spiekbrief (2024)

  • ysoserial-plus.jar – gemeenskapsvork met > 130 gadget kettings:
bash
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
  • marshalsec – steeds die verwysing vir JNDI gadget generasie (LDAP/RMI).
  • gadget-probe – vinnige swart-doos gadget ontdekking teen netwerk dienste.
  • SerialSniffer – JVMTI agent wat elke klas druk wat deur ObjectInputStream gelees word (nuttig om filters te skep).
  • Detectie wenk – aktiveer -Djdk.serialDebug=true (JDK 22+) om filterbesluite en verwerpte klasse te log.

Vinning checklist vir veilige readObject() implementasies

  1. Maak die metode privaat en voeg die @Serial annotasie by (help statiese analise).
  2. Moet nooit gebruikers-geleverde metodes aanroep of I/O in die metode uitvoer nie – lees slegs velde.
  3. As validasie nodig is, voer dit na deserialisering uit, buite readObject().
  4. Verkies om Externalizable te implementeer en doen eksplisiete veldlesings in plaas van standaard serialisering.
  5. Registreer 'n geharde ObjectInputFilter selfs vir interne dienste (kompromieer-bestande ontwerp).

Verwysings

  1. Spring Security Advisory – CVE-2023-34040 Java Deserialisering in Spring-Kafka (Aug 2023)
  2. GitHub Security Lab – GHSL-2023-044: Onveilige Deserialisering in Aerospike Java Kliënt (Jul 2023)

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks