diff --git a/src/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md b/src/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md index 4cc237ff5..6471129fc 100644 --- a/src/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md +++ b/src/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md @@ -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 ** ```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`, 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}}