# Msingi wa Java Deserialization na ObjectInputStream readObject {{#include ../../banners/hacktricks-training.md}} Katika POST hii itafafanuliwa mfano unaotumia `java.io.Serializable` **na kwa nini kuandika upya `readObject()` kunaweza kuwa hatari sana ikiwa mtiririko wa kuingia unadhibitiwa na mshambuliaji**. ## Serializable Interface ya Java `Serializable` (`java.io.Serializable`) ni interface ya alama ambayo madarasa yako yanapaswa kutekeleza ikiwa yanapaswa kuwa **serialized** na **deserialized**. Serialization ya kitu cha Java (kuandika) inafanywa na [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html) na deserialization (kusoma) inafanywa na [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html). ### Kumbusho: Ni mbinu zipi zinazoitwa kimya kimya wakati wa deserialization? 1. `readObject()` – mantiki ya kusoma maalum kwa darasa (ikiwa imeandikwa na *binafsi*). 2. `readResolve()` – inaweza kubadilisha kitu kilichodeserialized na kingine. 3. `validateObject()` – kupitia `ObjectInputValidation` callbacks. 4. `readExternal()` – kwa madarasa yanayotekeleza `Externalizable`. 5. Waandishi hawatekelezwi – kwa hivyo mnyororo wa gadget unategemea pekee callbacks za awali. Mbinu yoyote katika mnyororo huo inayomaliza kwa kuita data inayodhibitiwa na mshambuliaji (utendaji wa amri, utafutaji wa JNDI, reflection, nk.) inageuza utaratibu wa deserialization kuwa gadget ya RCE. Hebu tuone mfano na **darasa la Person** ambalo ni **serializable**. Darasa hili **linandika upya** kazi ya readObject, hivyo wakati **kitu chochote** cha **darasa hili** kinapokuwa **deserialized** kazi hii itatekelezwa.\ Katika mfano, kazi ya **readObject** ya darasa la Person inaita kazi `eat()` ya mnyama wake na kazi `eat()` ya Mbwa (kwa sababu fulani) inaita **calc.exe**. **Tutashuhudia jinsi ya kuandika na kusoma kitu cha Person ili kutekeleza kalkuleta hii:** **Mfano ufuatao unatoka ** ```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"); } } ``` ### Hitimisho (hali ya kawaida) Kama unavyoona katika mfano huu wa msingi, “udhaifu” hapa unatokea kwa sababu ya **method ya readObject()** **kuita nambari nyingine inayodhibitiwa na mshambuliaji**. Katika mnyororo wa vifaa wa ulimwengu halisi, maelfu ya madarasa yaliyomo katika maktaba za nje (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, nk.) yanaweza kutumika vibaya – mshambuliaji anahitaji tu *moja* ya vifaa vinavyoweza kufikiwa ili kupata utekelezaji wa nambari. --- ## 2023-2025: Nini kipya katika mashambulizi ya deserialization ya Java? * 2023 – CVE-2023-34040: Deserialization ya vichwa vya rekodi za makosa ya Spring-Kafka wakati bendera za `checkDeserExWhen*` zimewezeshwa ziliruhusu ujenzi wa vifaa vya kiholela kutoka kwa mada zilizochapishwa na mshambuliaji. Imerekebishwa katika 3.0.10 / 2.9.11. ¹ * 2023 – CVE-2023-36480: Dhana ya mteja wa Java wa Aerospike ya seva inayotegemewa imevunjwa – majibu ya seva yenye uharibifu yalikuwa na mzigo wa serialized ambao ulitafsiriwa na mteja → RCE. ² * 2023 – CVE-2023-25581: Ufafanuzi wa sifa za wasifu wa mtumiaji wa `pac4j-core` ulikubali blobs za Base64 zilizo na `{#sb64}` na kuziunda licha ya `RestrictedObjectInputStream`. Sasisha ≥ 4.0.0. * 2023 – CVE-2023-4528: Huduma ya JSCAPE MFT Manager (bandari 10880) ilikubali vitu vya Java vilivyoandikwa kwa XML vinavyosababisha RCE kama root/SYSTEM. * 2024 – Mnyororo mpya wa vifaa kadhaa uliongezwa kwa ysoserial-plus(mod) ikiwa ni pamoja na madarasa ya Hibernate5, TomcatEmbed, na SnakeYAML 2.x ambayo yanapita baadhi ya filters za zamani. ## Kinga za kisasa unazopaswa kutekeleza 1. **JEP 290 / Ufiltraji wa Serialization (Java 9+)** *Ongeza orodha ya ruhusa au orodha ya kukataa ya madarasa:* ```bash # Kubali tu DTO zako na java.base, kataa kila kitu kingine -Djdk.serialFilter="com.example.dto.*;java.base/*;!*" ``` Mfano wa programu: ```java var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" ); ObjectInputFilter.Config.setSerialFilter(filter); ``` 2. **JEP 415 (Java 17+) Kiwanda Maalum cha Filters** – tumia `BinaryOperator` kutekeleza filters tofauti kwa kila muktadha wa utekelezaji (kwa mfano, kwa kila wito wa RMI, kwa kila mtumiaji wa foleni ya ujumbe). 3. **Usifichue `ObjectInputStream` mbichi kwenye mtandao** – pendelea uandishi wa JSON/Binary bila maana ya utekelezaji wa nambari (Jackson baada ya kuzima `DefaultTyping`, Protobuf, Avro, nk.). 4. **Mipaka ya Ulinzi wa Kina** – Weka urefu wa juu wa array, kina, marejeleo: ```bash -Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000" ``` 5. **Kuchunguza vifaa kwa muda mrefu** – endesha zana kama `gadget-inspector` au `serialpwn-cli` katika CI yako ili kushindwa kwa ujenzi ikiwa kifaa hatari kinapatikana. ## Orodha ya zana iliyosasishwa (2024) * `ysoserial-plus.jar` – tawi la jamii lenye > 130 mnyororo wa vifaa: ```bash java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0 ``` * `marshalsec` – bado ni rejeleo kwa uzalishaji wa vifaa vya JNDI (LDAP/RMI). * `gadget-probe` – ugunduzi wa haraka wa vifaa vya black-box dhidi ya huduma za mtandao. * `SerialSniffer` – wakala wa JVMTI unaochapisha kila darasa lilosomwa na `ObjectInputStream` (linafaida katika kuunda filters). * **Ushauri wa kugundua** – wezesha `-Djdk.serialDebug=true` (JDK 22+) ili kuandika maamuzi ya filter na madarasa yaliyokataliwa. ## Orodha ya haraka ya ukaguzi kwa utekelezaji salama wa `readObject()` 1. Fanya method iwe `private` na ongeza annotation ya `@Serial` (inasaidia uchambuzi wa statiki). 2. Kamwe usiite mbinu zinazotolewa na mtumiaji au ufanye I/O katika method – soma tu maeneo. 3. Ikiwa uthibitisho unahitajika, fanya baada ya deserialization, nje ya `readObject()`. 4. Pendelea kutekeleza `Externalizable` na fanya usomaji wa maeneo wazi badala ya serialization ya kawaida. 5. Jisajili `ObjectInputFilter` iliyoimarishwa hata kwa huduma za ndani (muundo unaostahimili kuathiriwa). ## Marejeleo 1. Spring Security Advisory – CVE-2023-34040 Java Deserialization katika Spring-Kafka (Agosti 2023) 2. GitHub Security Lab – GHSL-2023-044: Deserialization Hatari katika Mteja wa Java wa Aerospike (Julai 2023) {{#include ../../banners/hacktricks-training.md}}