Translated ['src/pentesting-web/deserialization/basic-java-deserializati

This commit is contained in:
Translator 2025-07-28 18:12:48 +00:00
parent d20e7a8adb
commit 5c30e8779c

View File

@ -1,15 +1,27 @@
# Osnovna Java Deserializacija sa ObjectInputStream readObject
{{#include ../../banners/hacktricks-training.md}}
U ovom POST-u će biti objašnjen primer korišćenja `java.io.Serializable`.
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
## Serializable
Java `Serializable` interfejs (`java.io.Serializable` je marker interfejs koji vaše klase moraju implementirati ako žele da budu **serializovane** i **deserializovane**. Java objektna serializacija (pisanje) se vrši pomoću [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html), a deserializacija (čitanje) se vrši pomoću [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
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`](http://tutorials.jenkov.com/java-io/objectoutputstream.html), a deserializacija (čitanje) se vrši pomoću [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Hajde da vidimo primer sa **klasom Person** koja je **serializovana**. Ova klasa **prepisuje funkciju readObject**, tako da kada se **bilo koji objekat** ove **klase** **deserializuje**, 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 serializujemo i deserializujemo objekat Person da bismo izvršili ovaj kalkulator:**
### Podsetnik: Koje metode se implicitno pozivaju tokom deserializacije?
**Sledeći primer je sa [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
1. `readObject()` logika čitanja specifična za klasu (ako je implementirana i *privatna*).
2. `readResolve()` može zameniti deserijalizovani objekat drugim.
3. `validateObject()` putem `ObjectInputValidation` povratnih poziva.
4. `readExternal()` za klase koje implementiraju `Externalizable`.
5. 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>**
```java
import java.io.Serializable;
import java.io.*;
@ -80,8 +92,63 @@ payloadTest("test.ser");
}
}
```
## Zaključak
### Zaključak (klasičan scenario)
Kao što možete videti u ovom vrlo osnovnom primeru, "ranjivost" ovde se pojavljuje jer **readObject** funkcija **poziva druge ranjive funkcije**.
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 poverovao u pretpostavku o serveru 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 uprkos `RestrictedObjectInputStream`. Ažurirajte ≥ 4.0.0.
* 2023 CVE-2023-4528: JSCAPE MFT Manager Service (port 10880) prihvatio je XML-enkodirane 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
1. **JEP 290 / Filtriranje serijalizacije (Java 9+)**
*Dodajte listu dozvoljenih ili zabranjenih klasa:*
```bash
# Prihvatite samo svoje DTO-ove i java.base, odbacite sve ostalo
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
```
Programatski primer:
```java
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
```
2. **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).
3. **Ne izlažite sirovi `ObjectInputStream` preko mreže** preferirajte JSON/Binary kodiranja bez semantike izvršenja koda (Jackson nakon onemogućavanja `DefaultTyping`, Protobuf, Avro, itd.).
4. **Ograničenja odbrane u dubini** Postavite maksimalnu dužinu niza, dubinu, reference:
```bash
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
```
5. **Kontinuirano skeniranje gadgeta** pokrenite alate kao što su `gadget-inspector` ili `serialpwn-cli` u vašem CI da biste prekinuli gradnju ako postane dostupan opasan gadget.
## Ažurirani alatni cheat-sheet (2024)
* `ysoserial-plus.jar` zajednički fork sa > 130 gadget lanaca:
```bash
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 čita `ObjectInputStream` (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
1. Napravite metodu `private` i dodajte `@Serial` anotaciju (pomaže statičkoj analizi).
2. Nikada ne pozivajte metode koje je obezbedio korisnik ili ne vršite I/O u metodi samo čitajte polja.
3. Ako je potrebna validacija, izvršite je **nakon** deserializacije, van `readObject()`.
4. Preferirajte implementaciju `Externalizable` i radite eksplicitna čitanja polja umesto podrazumevane serijalizacije.
5. Registrujte ojačani `ObjectInputFilter` čak i za interne usluge (dizajn otporan na kompromitaciju).
## Reference
1. Spring Security Advisory CVE-2023-34040 Java Deserialization u Spring-Kafka (avgust 2023)
2. GitHub Security Lab GHSL-2023-044: Nesigurna Deserializacija u Aerospike Java Klijentu (jul 2023)
{{#include ../../banners/hacktricks-training.md}}