Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-33701-Unsafe-Deserialization-in-OpenTelemetry-Java-Agent-RMI-Instrumentation — Análise técnica da CVE-2026-33701, uma vulnerabilidade de desserialização insegura na instrumentação RMI do OpenTelemetry Java Agent, incluindo condições de exploração, detalhes do patch e estratégias de mitigação. | Kitploit
Ferramentas/GitHubGitHub/pl4tyz/cve-2026-33701-unsafe-deserialization-in-opentelemetry-java-agent-rmi-instrumentation
Análise de VulnerabilidadesExploraçãoSegurança WebAprendizado e Educação
GitHubpl4tyz/cve-2026-33701-unsafe-deserialization-in-opentelemetry-java-agent-rmi-instrumentation

CVE-2026-33701-Unsafe-Deserialization-in-OpenTelemetry-Java-Agent-RMI-Instrumentation

Análise técnica da CVE-2026-33701, uma vulnerabilidade de desserialização insegura na instrumentação RMI do OpenTelemetry Java Agent, incluindo condições de exploração, detalhes do patch e estratégias de mitigação.

Ver Repositório
11há 6 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-33701 — Desserialização insegura na instrumentação RMI do agente Java OpenTelemetry

Gravidade: Crítica (CVSS v4.0: 9.3)
Versões afetadas: opentelemetry-javaagent < 2.26.1
Corrigido em: 2.26.1 (lançado em 23 de março de 2026)


Visão geral

O OpenTelemetry é provavelmente o framework de observabilidade mais amplamente adotado no ecossistema Java atualmente. O agente Java especificamente é usado por milhares de serviços de produção para instrumentar automaticamente aplicações para rastreamento, métricas e logging, sem exigir nenhuma alteração de código por parte do desenvolvedor. Você apenas o anexa como uma flag javaagent e ele faz tudo nos bastidores.

O que torna a CVE-2026-33701 interessante não é apenas a vulnerabilidade em si, é a natureza de como ela foi introduzida. O agente registra silenciosamente um endpoint RMI personalizado como efeito colateral de sua instrumentação RMI. Os desenvolvedores não sabem que ele está lá. Não está em nenhum código de aplicação. Não é algo que eles configuraram. O agente o colocou lá automaticamente, e para versões anteriores à 2.26.1, esse endpoint estava desserializando dados recebidos sem absolutamente nenhum filtro aplicado.

Se a aplicação já tivesse uma porta RMI ou JMX exposta, um atacante com acesso de rede a essa porta poderia enviar um payload serializado especialmente criado para o endpoint personalizado do agente e potencialmente alcançar execução remota de código com os privilégios do processo JVM. O detalhe é que a RCE requer uma cadeia de gadgets compatível presente no classpath da aplicação. Mais sobre isso adiante.


Como o Agente Instrumenta RMI

Quando o agente Java OTel se anexa a uma JVM, ele instrumenta chamadas RMI para propagação de contexto. A ideia é que quando um cliente RMI chama um método remoto, o agente precisa propagar o contexto de rastreamento atual para o lado do servidor, para que os spans se conectem corretamente através das fronteiras de serviço.

Para fazer isso, o agente registra seu próprio objeto RMI personalizado usando um ObjID codificado. Em ContextPropagator.java:

public static final ObjID CONTEXT_CALL_ID =
    new ObjID("io.opentelemetry.javaagent.context-call".hashCode());

Este ObjID é como o agente identifica seu próprio endpoint dentro do runtime RMI. Quando um cliente RMI instrumentado se conecta a um servidor, ele primeiro verifica se o servidor tem este ObjID registrado. Se tiver, ele envia um payload de propagação de contexto para ele. Se não, ele pula a propagação de contexto e apenas faz a chamada regular.

O problema é que este endpoint é registrado dentro do runtime RMI da JVM, o que significa que ele compartilha o mesmo transporte que qualquer porta RMI ou JMX que a aplicação tenha aberta. Se a aplicação tem -Dcom.sun.management.jmxremote.port definido, ou se ela exporta seus próprios serviços RMI, o endpoint do agente é alcançável nessa mesma porta por qualquer pessoa que possa se conectar a ela.


O Código Vulnerável

A desserialização acontece em ContextPayload.java. Em versões anteriores à 2.26.1, o método read() era assim:

@SuppressWarnings("BanSerializableRead") // fine
public static ContextPayload read(ObjectInput oi) throws IOException {
    try {
        Object object = oi.readObject();
        if (object instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, String> map = (Map<String, String>) object;
            return new ContextPayload(map);
        }
    } catch (ClassCastException | ClassNotFoundException ex) {
        logger.log(FINE, "Error reading object", ex);
    }
    return null;
}

A anotação @SuppressWarnings("BanSerializableRead") com o comentário // fine é na verdade bastante reveladora. Alguém na equipe sinalizou isso como uma preocupação em algum momento, a supressão foi adicionada, e o comentário foi destinado a justificá-la. Claramente não estava tudo bem.

oi.readObject() sem filtros de serialização é o padrão clássico de desserialização insegura. A serialização Java instanciará felizmente qualquer classe no classpath durante a desserialização, e se o atacante puder controlar o fluxo serializado, ele pode escolher quais classes são instanciadas e em que ordem. Essa é a base dos ataques de cadeia de gadgets.

O código verifica instanceof Map após a desserialização, mas nesse ponto o dano já está feito. A cadeia de gadgets executa durante a própria chamada readObject(), antes que qualquer verificação de tipo aconteça. A verificação instanceof é completamente irrelevante do ponto de vista de segurança.


O Patch

A correção na 2.26.1 substitui completamente a abordagem de desserialização. Em vez de serializar um objeto Map e chamar readObject(), a nova implementação lê manualmente as entradas de contexto como tipos primitivos:

@Nullable
public static ContextPayload read(ObjectInput oi) throws IOException {
    int size = oi.readInt();
    if (size > MAX_CONTEXT_ENTRIES) {
        logger.log(
            FINE,
            "RMI context propagation payload size {0} exceeds maximum allowed of {1}, skipping context propagation.",
            new Object[] {size, MAX_CONTEXT_ENTRIES});
        return null;
    }
    Map<String, String> map = new HashMap<>();
    for (int i = 0; i < size; i++) {
        String key = oi.readUTF();
        String value = oi.readUTF();
        map.put(key, value);
    }
    return new ContextPayload(map);
}

E o lado de escrita foi atualizado para corresponder:

public void write(ObjectOutput out) throws IOException {
    int size = context.size();
    if (size > MAX_CONTEXT_ENTRIES) {
        out.writeInt(0);
        return;
    }
    out.writeInt(size);
    for (Map.Entry<String, String> entry : context.entrySet()) {
        out.writeUTF(entry.getKey());
        out.writeUTF(entry.getValue());
    }
}

Esta abordagem apenas lê tipos primitivos (ints e strings UTF) do fluxo. Não há instanciação de objetos acontecendo. Nenhuma cadeia de gadgets pode executar através de readInt() ou readUTF(). A correção está correta e completa.

Há também uma segunda mudança que vale a pena notar. O ObjID usado para identificar o endpoint personalizado do agente foi versionado:

// Antes (2.26.0)
new ObjID("io.opentelemetry.javaagent.context-call".hashCode());

// Depois (2.26.1)
new ObjID("io.opentelemetry.javaagent.context-call-v2".hashCode());

Isso significa que um agente corrigido não responderá ao ObjID antigo de forma alguma. Um atacante mirando o endpoint antigo não obteria resposta de um servidor corrigido. Esta é uma boa medida adicional de endurecimento além da correção de desserialização, ela efetivamente quebra qualquer exploit que foi construído contra o endpoint v1, mesmo que de alguma forma a desserialização ainda fosse alcançável.


Condições de Exploração

Todas as três condições a seguir devem ser verdadeiras simultaneamente para que isso seja explorável:

1. Agente Java OpenTelemetry anexado em JDK 16 ou inferior

Esta é a restrição mais importante. O JDK 17 introduziu mudanças significativas nos internals do RMI e impõe encapsulamento de módulos muito mais estrito através do Java Platform Module System. A maioria das cadeias de gadgets que funcionam contra a desserialização Java depende de reflexão para acessar classes internas do JDK ou para invocar métodos que normalmente não seriam acessíveis. O JDK 17 quebra esses caminhos de reflexão por padrão devido ao encapsulamento forte, o que significa que a maioria das cadeias de gadgets conhecidas simplesmente não funciona no JDK 17 e superior.

No JDK 8, 11 e 16, no entanto, o acesso por reflexão é muito mais permissivo e as cadeias de gadgets funcionam como esperado. Essas versões do JDK ainda representam uma parcela substancial das implantações Java em produção, especialmente em ambientes empresariais mais antigos.

Baixar ferramenta