
Proof-of-concept che dimostra un bypass del filtro di deserializzazione in Apache MINA che porta all'esecuzione remota di codice, con analisi dettagliata della causa principale, PoC di exploit e indicazioni di rimedio.
CVSS 3.1: 9.8 CRITICO AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-502 Deserializzazione di dati non attendibili
Segnalatore: Venkatraman Kumar, Securin
Avviso: Mailing list Apache
Le versioni di Apache MINA dalla 2.1.0 alla 2.1.11 e dalla 2.2.0 alla 2.2.6 contengono un bypass del filtro di deserializzazione in AbstractIoBuffer.resolveClass(). La lista consentita acceptMatchers — progettata per limitare quali classi Java possono essere deserializzate — viene completamente saltata quando ObjectStreamClass.forClass() restituisce null.
Un attaccante con accesso di rete a un endpoint MINA che utilizza ObjectSerializationCodecFactory può creare un payload di protocollo che bypassa il filtro delle classi, consentendo la piena esecuzione remota di codice tramite catene di gadget standard di deserializzazione Java (ad es., Commons Collections).
Si tratta di una correzione incompleta per CVE-2026-41635. La patch originale è stata applicata al ramo 2.0.x ma non è mai stata portata ai rami 2.1.x o 2.2.x a causa di una svista durante il merge.
| Ramo | Vulnerabile | Corretta |
|---|---|---|
| 2.1.x | 2.1.0 – 2.1.11 | 2.1.12 |
| 2.2.x | 2.2.0 – 2.2.6 | 2.2.7 |
La vulnerabilità si trova in AbstractIoBuffer.resolveClass(), che gestisce la risoluzione delle classi durante la deserializzazione di oggetti Java.
MINA utilizza un protocollo di serializzazione personalizzato con due tipi di descrittori di classe:
Nel codice vulnerabile, il filtro acceptMatchers viene controllato solo nel ramo di tipo 1 (quando forClass() restituisce un valore non nullo). Il ramo di tipo 0 chiama direttamente Class.forName(), bypassando completamente il filtro:
// AbstractIoBuffer.java — VULNERABILE (2.2.6)
protected Class<?> resolveClass(ObjectStreamClass desc) {
Class<?> clazz = desc.forClass();
if (clazz == null) {
// BUG: Nessun controllo acceptMatchers — filtro completamente bypassato
return Class.forName(name, false, classLoader);
} else {
// Il filtro viene applicato solo qui
for (ClassNameMatcher matcher : acceptMatchers) { ... }
}
}
La correzione nella 2.2.7 sposta il controllo del filtro prima del ramo:
// AbstractIoBuffer.java — CORRETTO (2.2.7)
protected Class<?> resolveClass(ObjectStreamClass desc) {
String className = desc.getName();
// Filtro applicato PRIMA, indipendentemente dal risultato di forClass()
if (!acceptMatchers.stream().anyMatch(m -> m.matches(className))) {
throw new ClassNotFoundException("Class not in accept list " + className);
}
Class<?> clazz = desc.forClass();
// ... la risoluzione sicura prosegue
}
Attaccante Server MINA vulnerabile
| |
| 1. Crea un payload MINA con descrittori |
| di tipo 0 per le classi della catena |
| di gadget |
| |
| 2. Invia all'endpoint che utilizza |
| ObjectSerializationCodecFactory -------->|
| |
| 3. readClassDescriptor() legge il tipo 0
| → delega al super (Java standard) |
| |
| 4. resolveClass() vede forClass()==null
| → Class.forName() SENZA filtro |
| |
| 5. La catena di gadget viene |
| completamente deserializzata |
| → readObject() attiva la catena |
| → Runtime.exec() viene eseguito |
| |
| RCE OTTENUTA |
IoBuffer.getObject() o ObjectSerializationCodecFactoryaccept() configurato (le applicazioni senza filtro erano già sfruttabili tramite CVE-2026-41635)L'attaccante controlla il flusso di byte serializzato. Utilizzando descrittori di classe di tipo 0 (invece del tipo 1) per le classi Serializable della catena di gadget, ogni classe nel grafo di deserializzazione bypassa il filtro acceptMatchers, indipendentemente dalla configurazione della lista consentita dell'applicazione.
Tre PoC dimostrano un impatto crescente:
| PoC | Cosa dimostra |
|---|---|
FilterBypassPoC.java | Bypass del filtro per primitivi, classi non-Serializable, array |
CraftedBypassPoC.java | Payload di tipo 0 creati dall'attaccante bypassano il filtro per QUALSIASI classe Serializable |
RcePoC.java | RCE completa tramite la catena di gadget CC6 attraverso il bypass del filtro |
Le classi non presenti nella lista consentita vengono deserializzate senza restrizioni:

Un attaccante crea payload di protocollo MINA con descrittori di tipo 0 per caricare qualsiasi classe oltre una lista consentita di soli String:

La catena di gadget variante CC6 (HashSet → TiedMapEntry → LazyMap → ChainedTransformer → Runtime.exec()) ottiene l'esecuzione di comandi attraverso il bypass del filtro:

Gli stessi test vengono bloccati sulla versione corretta:

La catena di gadget viene respinta dal filtro:

Il modo più veloce per testare — nessun JDK o Maven richiesto:
# Clona questo repository
git clone https://github.com/dinosn/CVE-2026-42779.git
cd CVE-2026-42779
# Compila ed esegui tutti i PoC
docker build -t cve-2026-42779 .
docker run --rm cve-2026-42779
# Esegui singoli PoC
docker run --rm cve-2026-42779 bypass # Solo bypass del filtro
docker run --rm cve-2026-42779 crafted # Bypass del payload creato
docker run --rm cve-2026-42779 rce # RCE completa