Osnovna Java Deserializacija sa ObjectInputStream readObject
Reading time: 6 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
U ovom POST-u će biti objašnjen primer korišćenja java.io.Serializable
i zašto prepisivanje readObject()
može biti izuzetno opasno ako je dolazni tok podataka pod kontrolom napadača.
Serializable
Java Serializable
interfejs (java.io.Serializable
) je marker interfejs koji vaše klase moraju implementirati ako žele da budu serijalizovane i deserijalizovane. Java serijalizacija objekata (pisanje) se vrši pomoću ObjectOutputStream
, a deserializacija (čitanje) se vrši pomoću ObjectInputStream
.
Podsetnik: Koje metode se implicitno pozivaju tokom deserializacije?
readObject()
– logika čitanja specifična za klasu (ako je implementirana i privatna).readResolve()
– može zameniti deserializovani objekat drugim.validateObject()
– putemObjectInputValidation
povratnih poziva.readExternal()
– za klase koje implementirajuExternalizable
.- Konstruktori se ne izvršavaju – stoga lanci gadgeta oslanjaju se isključivo na prethodne povratne pozive.
Svaka metoda u tom lancu koja završi pozivajući podatke pod kontrolom napadača (izvršavanje komandi, JNDI pretrage, refleksija, itd.) pretvara rutinu deserializacije u RCE gadget.
Pogledajmo primer sa klasom Person koja je serijalizovana. Ova klasa prepisuje funkciju readObject, tako da kada se bilo koji objekat ove klase deserijalizuje, ova funkcija će biti izvršena.
U primeru, readObject funkcija klase Person poziva funkciju eat()
njegovog ljubimca, a funkcija eat()
psa (iz nekog razloga) poziva calc.exe. Videćemo kako da serijalizujemo i deserijalizujemo objekat Person da bismo izvršili ovaj kalkulator:
Sledeći primer je sa 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");
}
}
Zaključak (klasičan scenario)
Kao što možete videti u ovom vrlo osnovnom primeru, "ranjivost" ovde se pojavljuje jer readObject() metoda poziva drugi kod pod kontrolom napadača. U stvarnim lancima gadgeta, hiljade klasa sadržanih u spoljnim bibliotekama (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, itd.) mogu biti zloupotrebljene – napadaču je potrebna jedna dostupna gadgeta da bi dobio izvršenje koda.
2023-2025: Šta je novo u Java deserialization napadima?
- 2023 – CVE-2023-34040: Spring-Kafka deserialization zaglavlja grešaka kada su
checkDeserExWhen*
zastavice omogućene omogućilo je proizvoljnu konstrukciju gadgeta iz tema koje je objavio napadač. Ispravljeno u 3.0.10 / 2.9.11. ¹ - 2023 – CVE-2023-36480: Aerospike Java klijent poverenje u server prekinuto – zlonamerne odgovore servera sadržale su serijalizovane payload-e koje je klijent deserializovao → RCE. ²
- 2023 – CVE-2023-25581:
pac4j-core
atribut profila korisnika prihvatio je{#sb64}
-prefiksirane Base64 blobove i deserializovao ih uprkosRestrictedObjectInputStream
. Ažurirajte ≥ 4.0.0. - 2023 – CVE-2023-4528: JSCAPE MFT Manager Service (port 10880) prihvatio je XML-encoded Java objekte što je dovelo do RCE kao root/SYSTEM.
- 2024 – Više novih gadget lanaca je dodato u ysoserial-plus(mod) uključujući Hibernate5, TomcatEmbed i SnakeYAML 2.x klase koje zaobilaze neke stare filtere.
Moderne mitigacije koje treba primeniti
- JEP 290 / Filtriranje serijalizacije (Java 9+) Dodajte listu dozvoljenih ili zabranjenih klasa:
# Prihvatite samo svoje DTO-ove i java.base, odbacite sve ostalo
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
Programatski primer:
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
- JEP 415 (Java 17+) Filter fabrike specifične za kontekst – koristite
BinaryOperator<ObjectInputFilter>
da primenite različite filtere po kontekstu izvršenja (npr. po RMI pozivu, po potrošaču poruka). - Ne izlažite sirovi
ObjectInputStream
preko mreže – preferirajte JSON/Binary kodiranja bez semantike izvršenja koda (Jackson nakon onemogućavanjaDefaultTyping
, Protobuf, Avro, itd.). - Ograničenja odbrane u dubini – Postavite maksimalnu dužinu niza, dubinu, reference:
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
- Kontinuirano skeniranje gadgeta – pokrenite alate kao što su
gadget-inspector
iliserialpwn-cli
u vašem CI da bi se izgradnja obustavila ako postane dostupna opasna gadgeta.
Ažurirani alatni cheat-sheet (2024)
ysoserial-plus.jar
– zajednički fork sa > 130 gadget lanaca:
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
marshalsec
– još uvek referenca za generisanje JNDI gadgeta (LDAP/RMI).gadget-probe
– brza crna kutija za otkrivanje gadgeta protiv mrežnih usluga.SerialSniffer
– JVMTI agent koji ispisuje svaku klasu koju čitaObjectInputStream
(korisno za kreiranje filtera).- Saveta za detekciju – omogućite
-Djdk.serialDebug=true
(JDK 22+) da biste zabeležili odluke filtera i odbijene klase.
Brza lista provere za sigurne readObject()
implementacije
- Napravite metodu
private
i dodajte@Serial
anotaciju (pomaže statičkoj analizi). - Nikada ne pozivajte metode koje je obezbedio korisnik ili ne vršite I/O u metodi – samo čitajte polja.
- Ako je potrebna validacija, izvršite je nakon deserializacije, van
readObject()
. - Preferirajte implementaciju
Externalizable
i izvršite eksplicitna čitanja polja umesto podrazumevane serijalizacije. - Registrujte ojačani
ObjectInputFilter
čak i za interne usluge (dizajn otporan na kompromitaciju).
Reference
- Spring Security Advisory – CVE-2023-34040 Java Deserialization u Spring-Kafka (avgust 2023)
- GitHub Security Lab – GHSL-2023-044: Nesigurna Deserializacija u Aerospike Java Klijentu (jul 2023)
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.