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