mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
155 lines
8.1 KiB
Markdown
155 lines
8.1 KiB
Markdown
# 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 maalum ya kusoma ya 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 inayomalizika 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 umetolewa kutoka <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");
|
||
}
|
||
}
|
||
```
|
||
### Hitimisho (hali ya kawaida)
|
||
|
||
Kama unavyoona katika mfano huu wa msingi, “udhaifu” hapa unatokea kwa sababu ya **metode ya readObject()** **kuita msimbo mwingine unaodhibitiwa 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 msimbo.
|
||
|
||
---
|
||
|
||
## 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. Imefanyiwa marekebisho 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 mizigo iliyosimbwa ambayo ilitafsiriwa na mteja → RCE. ²
|
||
* 2023 – CVE-2023-25581: Uchanganuzi 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 vingi 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 kutumia
|
||
|
||
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<ObjectInputFilter>` kutekeleza filters tofauti kwa kila muktadha wa utekelezaji (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 za utekelezaji wa msimbo (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 sanduku jeusi dhidi ya huduma za mtandao.
|
||
* `SerialSniffer` – wakala wa JVMTI unaochapisha kila darasa lilosomwa na `ObjectInputStream` (inayofaa kutengeneza 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 njia hiyo kuwa `private` na ongeza annotation ya `@Serial` (inasaidia uchambuzi wa statiki).
|
||
2. Kamwe usiite mbinu zinazotolewa na mtumiaji au ufanye I/O katika njia hiyo – soma tu maeneo.
|
||
3. Ikiwa uthibitisho unahitajika, fanya baada ya deserialization, nje ya `readObject()`.
|
||
4. Pendelea kutekeleza `Externalizable` na ufanye usomaji wa maeneo wazi badala ya serialization ya kawaida.
|
||
5. Sajili `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}}
|