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

This commit is contained in:
Translator 2025-07-28 18:13:07 +00:00
parent 91c08365b6
commit 1f1403503e

View File

@ -1,15 +1,27 @@
# Basic Java Deserialization with ObjectInputStream readObject
{{#include ../../banners/hacktricks-training.md}}
In questo POST verrà spiegato un esempio utilizzando `java.io.Serializable`.
In questo POST verrà spiegato un esempio utilizzando `java.io.Serializable` **e perché sovrascrivere `readObject()` può essere estremamente pericoloso se il flusso in arrivo è controllato dall'attaccante**.
# Serializable
## Serializable
L'interfaccia Java `Serializable` (`java.io.Serializable` è un'interfaccia marker che le tue classi devono implementare se devono essere **serializzate** e **deserializzate**. La serializzazione degli oggetti Java (scrittura) viene eseguita con l'[ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) e la deserializzazione (lettura) viene eseguita con l'[ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
L'interfaccia Java `Serializable` (`java.io.Serializable`) è un'interfaccia marker che le tue classi devono implementare se devono essere **serializzate** e **deserializzate**. La serializzazione degli oggetti Java (scrittura) viene eseguita con [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html) e la deserializzazione (lettura) viene eseguita con [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Vediamo un esempio con una **classe Person** che è **serializzabile**. Questa classe **sovrascrive la funzione readObject**, quindi quando **qualunque oggetto** di questa **classe** viene **deserializzato**, questa **funzione** verrà **eseguita**.\
### Promemoria: Quali metodi vengono invocati implicitamente durante la deserializzazione?
1. `readObject()` logica di lettura specifica della classe (se implementata e *privata*).
2. `readResolve()` può sostituire l'oggetto deserializzato con un altro.
3. `validateObject()` tramite callback `ObjectInputValidation`.
4. `readExternal()` per classi che implementano `Externalizable`.
5. I costruttori **non** vengono eseguiti pertanto le catene di gadget si basano esclusivamente sui callback precedenti.
Qualsiasi metodo in quella catena che finisce per invocare dati controllati dall'attaccante (esecuzione di comandi, ricerche JNDI, riflessione, ecc.) trasforma la routine di deserializzazione in un gadget RCE.
Vediamo un esempio con una **classe Person** che è **serializzabile**. Questa classe **sovrascrive la funzione readObject**, quindi quando **qualsiasi oggetto** di questa **classe** viene **deserializzato**, questa **funzione** verrà **eseguita**.\
Nell'esempio, la **funzione readObject** della classe Person chiama la funzione `eat()` del suo animale domestico e la funzione `eat()` di un Cane (per qualche motivo) chiama un **calc.exe**. **Vedremo come serializzare e deserializzare un oggetto Person per eseguire questa calcolatrice:**
**Il seguente esempio è tratto da [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
**Il seguente esempio è tratto da <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");
}
}
```
## Conclusione
### Conclusione (scenario classico)
Come puoi vedere in questo esempio molto basilare, la "vulnerabilità" qui appare perché la funzione **readObject** sta **chiamando altre funzioni vulnerabili**.
Come puoi vedere in questo esempio molto basilare, la “vulnerabilità” qui appare perché il metodo **readObject()** sta **chiamando altro codice controllato dall'attaccante**. Nelle catene di gadget del mondo reale, migliaia di classi contenute in librerie esterne (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, ecc.) possono essere abusate l'attaccante ha bisogno solo di *uno* gadget raggiungibile per ottenere l'esecuzione del codice.
---
## 2023-2025: Novità negli attacchi di deserializzazione Java?
* 2023 CVE-2023-34040: La deserializzazione degli header dei record di errore di Spring-Kafka quando i flag `checkDeserExWhen*` sono abilitati ha permesso la costruzione arbitraria di gadget da argomenti pubblicati dall'attaccante. Risolto in 3.0.10 / 2.9.11. ¹
* 2023 CVE-2023-36480: Assunzione di server fidati del client Java Aerospike rotta le risposte del server malevole contenevano payload serializzati che sono stati deserializzati dal client → RCE. ²
* 2023 CVE-2023-25581: L'analisi degli attributi del profilo utente di `pac4j-core` accettava blob Base64 con prefisso `{#sb64}` e li deserializzava nonostante un `RestrictedObjectInputStream`. Aggiorna ≥ 4.0.0.
* 2023 CVE-2023-4528: Il servizio JSCAPE MFT Manager (porta 10880) accettava oggetti Java codificati in XML portando a RCE come root/SYSTEM.
* 2024 Sono state aggiunte nuove catene di gadget a ysoserial-plus(mod) inclusi Hibernate5, TomcatEmbed e classi SnakeYAML 2.x che bypassano alcuni vecchi filtri.
## Mitigazioni moderne che dovresti implementare
1. **JEP 290 / Filtro di Serializzazione (Java 9+)**
*Aggiungi una lista di autorizzazione o di negazione delle classi:*
```bash
# Accetta solo i tuoi DTO e java.base, rifiuta tutto il resto
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
```
Esempio programmatico:
```java
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
```
2. **JEP 415 (Java 17+) Fabbriche di Filtri Specifici per Contesto** usa un `BinaryOperator<ObjectInputFilter>` per applicare filtri diversi per contesto di esecuzione (ad esempio, per chiamata RMI, per consumatore di coda di messaggi).
3. **Non esporre `ObjectInputStream` grezzo sulla rete** preferisci codifiche JSON/Binary senza semantiche di esecuzione del codice (Jackson dopo aver disabilitato `DefaultTyping`, Protobuf, Avro, ecc.).
4. **Limiti di Difesa in Profondità** Imposta lunghezza massima degli array, profondità, riferimenti:
```bash
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
```
5. **Scansione continua dei gadget** esegui strumenti come `gadget-inspector` o `serialpwn-cli` nel tuo CI per far fallire la build se un gadget pericoloso diventa raggiungibile.
## Scheda di riferimento degli strumenti aggiornata (2024)
* `ysoserial-plus.jar` fork della comunità con > 130 catene di gadget:
```bash
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
```
* `marshalsec` rimane il riferimento per la generazione di gadget JNDI (LDAP/RMI).
* `gadget-probe` scoperta rapida di gadget black-box contro servizi di rete.
* `SerialSniffer` agente JVMTI che stampa ogni classe letta da `ObjectInputStream` (utile per creare filtri).
* **Suggerimento per la rilevazione** abilita `-Djdk.serialDebug=true` (JDK 22+) per registrare le decisioni del filtro e le classi rifiutate.
## Checklist rapida per implementazioni sicure di `readObject()`
1. Rendi il metodo `private` e aggiungi l'annotazione `@Serial` (aiuta l'analisi statica).
2. Non chiamare metodi forniti dall'utente o eseguire I/O nel metodo leggi solo i campi.
3. Se è necessaria la validazione, eseguila **dopo** la deserializzazione, al di fuori di `readObject()`.
4. Preferisci implementare `Externalizable` e fare letture esplicite dei campi invece della serializzazione predefinita.
5. Registra un `ObjectInputFilter` rinforzato anche per i servizi interni (design resistente ai compromessi).
## Riferimenti
1. Avviso di Sicurezza di Spring CVE-2023-34040 Deserializzazione Java in Spring-Kafka (Ago 2023)
2. GitHub Security Lab GHSL-2023-044: Deserializzazione non sicura nel client Java Aerospike (Lug 2023)
{{#include ../../banners/hacktricks-training.md}}