mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/basic-java-deserializati
This commit is contained in:
parent
62d9188ffd
commit
d8c5df5dee
@ -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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user