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

This commit is contained in:
Translator 2025-07-28 18:12:38 +00:00
parent 62d9188ffd
commit d8c5df5dee

View File

@ -1,15 +1,27 @@
# Podstawowa deserializacja Java z ObjectInputStream readObject
{{#include ../../banners/hacktricks-training.md}}
W tym poście zostanie wyjaśniony przykład użycia `java.io.Serializable`.
W tym poście zostanie wyjaśniony przykład użycia `java.io.Serializable` **i dlaczego nadpisywanie `readObject()` może być niezwykle niebezpieczne, jeśli strumień przychodzący jest kontrolowany przez atakującego**.
# Serializable
## Serializable
Interfejs Java `Serializable` (`java.io.Serializable` to interfejs znacznikowy, który Twoje klasy muszą implementować, jeśli mają być **serializowane** i **deserializowane**. Serializacja obiektów Java (zapisywanie) odbywa się za pomocą [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html), a deserializacja (odczyt) za pomocą [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Interfejs Java `Serializable` (`java.io.Serializable`) jest interfejsem znacznikowym, który Twoje klasy muszą implementować, jeśli mają być **serializowane** i **deserializowane**. Serializacja obiektów Java (zapisywanie) odbywa się za pomocą [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html), a deserializacja (odczyt) za pomocą [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Zobaczmy przykład z **klasą Person**, która jest **serializowalna**. Ta klasa **przesłania funkcję readObject**, więc gdy **jakikolwiek obiekt** tej **klasy** jest **deserializowany**, ta **funkcja** zostanie **wykonana**.\
W przykładzie **funkcja readObject** klasy Person wywołuje funkcję `eat()` jego zwierzęcia, a funkcja `eat()` psa (z jakiegoś powodu) wywołuje **calc.exe**. **Zobaczymy, jak serializować i deserializować obiekt Person, aby uruchomić ten kalkulator:**
### Przypomnienie: Które metody są wywoływane automatycznie podczas deserializacji?
**Poniższy przykład pochodzi z [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 odczytu specyficzna dla klasy (jeśli zaimplementowana i *prywatna*).
2. `readResolve()` może zastąpić deserializowany obiekt innym.
3. `validateObject()` za pomocą wywołań zwrotnych `ObjectInputValidation`.
4. `readExternal()` dla klas implementujących `Externalizable`.
5. Konstruktory **nie** są wykonywane dlatego łańcuchy gadżetów polegają wyłącznie na poprzednich wywołaniach zwrotnych.
Każda metoda w tym łańcuchu, która kończy się na wywołaniu danych kontrolowanych przez atakującego (wykonanie polecenia, wyszukiwania JNDI, refleksja itp.) przekształca rutynę deserializacji w gadżet RCE.
Zobaczmy przykład z **klasą Person**, która jest **serializowalna**. Ta klasa **nadpisuje funkcję readObject**, więc gdy **jakikolwiek obiekt** tej **klasy** jest **deserializowany**, ta **funkcja** zostanie **wykonana**.\
W przykładzie, **funkcja readObject** klasy Person wywołuje funkcję `eat()` jego zwierzaka, a funkcja `eat()` psa (z jakiegoś powodu) wywołuje **calc.exe**. **Zobaczymy, jak serializować i deserializować obiekt Person, aby wykonać ten kalkulator:**
**Poniższy przykład pochodzi z <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");
}
}
```
## Wnioski
### Wnioski (klasyczny scenariusz)
Jak widać w tym bardzo podstawowym przykładzie, "vulnerability" tutaj pojawia się, ponieważ funkcja **readObject** **wywołuje inne podatne funkcje**.
Jak widać w tym bardzo podstawowym przykładzie, "vulnerability" tutaj pojawia się, ponieważ metoda **readObject()** **wywołuje inny kod kontrolowany przez atakującego**. W rzeczywistych łańcuchach gadżetów tysiące klas zawartych w zewnętrznych bibliotekach (Commons-Collections, Spring, Groovy, Rome, SnakeYAML itp.) mogą być nadużywane atakujący potrzebuje tylko *jednego* dostępnego gadżetu, aby uzyskać wykonanie kodu.
---
## 2023-2025: Co nowego w atakach deserializacji Java?
* 2023 CVE-2023-34040: Deserializacja nagłówków rekordów błędów Spring-Kafka, gdy flagi `checkDeserExWhen*` są włączone, umożliwiła dowolne konstruowanie gadżetów z tematów publikowanych przez atakujących. Naprawione w 3.0.10 / 2.9.11. ¹
* 2023 CVE-2023-36480: Założenie zaufanego serwera klienta Java Aerospike zostało złamane złośliwe odpowiedzi serwera zawierały zserializowane ładunki, które zostały zdeserializowane przez klienta → RCE. ²
* 2023 CVE-2023-25581: Analiza atrybutu profilu użytkownika `pac4j-core` akceptowała zprefiksowane `{#sb64}` bloby Base64 i zdeserializowała je pomimo `RestrictedObjectInputStream`. Uaktualnij ≥ 4.0.0.
* 2023 CVE-2023-4528: Usługa JSCAPE MFT Manager (port 10880) akceptowała obiekty Java zakodowane w XML, co prowadziło do RCE jako root/SYSTEM.
* 2024 Dodano wiele nowych łańcuchów gadżetów do ysoserial-plus(mod), w tym klasy Hibernate5, TomcatEmbed i SnakeYAML 2.x, które omijają niektóre stare filtry.
## Nowoczesne środki zaradcze, które powinieneś wdrożyć
1. **JEP 290 / Filtrowanie serializacji (Java 9+)**
*Dodaj listę dozwolonych lub zablokowanych klas:*
```bash
# Akceptuj tylko swoje DTO i java.base, odrzucaj wszystko inne
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
```
Przykład programowy:
```java
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
```
2. **JEP 415 (Java 17+) Fabryki filtrów specyficznych dla kontekstu** użyj `BinaryOperator<ObjectInputFilter>`, aby zastosować różne filtry w zależności od kontekstu wykonania (np. na podstawie wywołania RMI, konsumenta kolejki wiadomości).
3. **Nie wystawiaj surowego `ObjectInputStream` przez sieć** preferuj kodowania JSON/Binary bez semantyki wykonania kodu (Jackson po wyłączeniu `DefaultTyping`, Protobuf, Avro itp.).
4. **Ograniczenia obrony w głębokości** Ustaw maksymalną długość tablicy, głębokość, odniesienia:
```bash
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
```
5. **Ciągłe skanowanie gadżetów** uruchamiaj narzędzia takie jak `gadget-inspector` lub `serialpwn-cli` w swoim CI, aby przerwać budowę, jeśli niebezpieczny gadżet stanie się dostępny.
## Zaktualizowana ściągawka narzędziowa (2024)
* `ysoserial-plus.jar` fork społeczności z > 130 łańcuchami gadżetów:
```bash
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
```
* `marshalsec` nadal odniesienie do generacji gadżetów JNDI (LDAP/RMI).
* `gadget-probe` szybkie odkrywanie gadżetów czarnej skrzynki przeciwko usługom sieciowym.
* `SerialSniffer` agent JVMTI, który drukuje każdą klasę odczytaną przez `ObjectInputStream` (przydatne do tworzenia filtrów).
* **Wskazówka dotycząca wykrywania** włącz `-Djdk.serialDebug=true` (JDK 22+), aby rejestrować decyzje filtrów i odrzucone klasy.
## Szybka lista kontrolna dla bezpiecznych implementacji `readObject()`
1. Uczyń metodę `private` i dodaj adnotację `@Serial` (pomaga w analizie statycznej).
2. Nigdy nie wywołuj metod dostarczonych przez użytkownika ani nie wykonuj operacji I/O w metodzie tylko odczytuj pola.
3. Jeśli potrzebna jest walidacja, wykonaj ją **po** deserializacji, poza `readObject()`.
4. Preferuj implementację `Externalizable` i wykonuj jawne odczyty pól zamiast domyślnej serializacji.
5. Zarejestruj wzmocniony `ObjectInputFilter` nawet dla usług wewnętrznych (projekt odporny na kompromitacje).
## Odnośniki
1. Spring Security Advisory CVE-2023-34040 Deserializacja Java w Spring-Kafka (sierpień 2023)
2. GitHub Security Lab GHSL-2023-044: Niebezpieczna deserializacja w kliencie Java Aerospike (lipiec 2023)
{{#include ../../banners/hacktricks-training.md}}