
CVE-2026-88789 के लिए रन करने योग्य proof-of-concept reproducer, जो Apache Camel Quarkus camel-quarkus-support-xalan में XSLT TransformerFactory के माध्यम से XXE और SSRF को प्रदर्शित करता है।
TransformerFactory JAXP बाहरी पहुँच प्रतिबंधों को हटा देता हैApache Camel Quarkus भेद्यता के लिए चलाने योग्य proof-of-concept reproducer, जहाँ XSLT समर्थन
एक्सटेंशन (camel-quarkus-support-xalan) xslt कंपोनेंट को अपना Xalan-आधारित TransformerFactory प्रदान करता है
और उसे JAXP डिफ़ॉल्ट के रूप में पंजीकृत करता है। Xalan-J 2.7.x, JAXP 1.5 से पहले का है और
javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD या ACCESS_EXTERNAL_STYLESHEET का पालन नहीं कर सकता — दोनों के लिए
setAttribute() IllegalArgumentException फेंकता है — इसलिए Apache Camel द्वारा अपने बनाए गए
TransformerFactory पर लागू किए गए बाहरी पहुँच प्रतिबंध कभी प्रभावी ही नहीं थे।
| Runtime | Directory | Stack |
|---|---|---|
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.36.0 (Quarkus 3.36.0, Camel 4.20.0) |
केवल Camel Quarkus। भेद्य कोड एक Camel Quarkus एक्सटेंशन है, Camel कंपोनेंट नहीं। सादा Camel और Camel Spring Boot JDK के
TransformerFactoryका उपयोग करते हैं, जो दोनों विशेषताओं का पालन करता है, इसलिए वहाँ पुनरुत्पादन के लिए कुछ नहीं है — इसलिए इस रिपॉज़िटरी मेंcamel-spring-boot/संस्करण नहीं है।
एक हमलावर जो रूपांतरित किए जा रहे XML दस्तावेज़ को प्रदान करता है, वह उस दस्तावेज़ में बाहरी entity घोषणा के माध्यम से स्थानीय फ़ाइलें पढ़ सकता है या आंतरिक नेटवर्क स्थानों तक पहुँच सकता है।
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
प्रभावित बिल्ड पर अपेक्षित आउटपुट (संक्षिप्त — ड्राइवर छह प्रोब चलाता है, देखें
camel-quarkus/README.md):
1) xslt endpoint, body is a StreamSource, external entity -> file:///tmp/cve-2026-88789-secrets/db-password.txt
transformation result: [db.password=LOCAL-FILE-s3cr3t-99]
local file contents in the output: true
2) xslt endpoint, body is a StreamSource, external entity -> http://127.0.0.1:8080/internal/secret
transformation result: [INTERNAL-SECRET-s3cr3t-42]
internal endpoint response in the output: true
4) CONTROL - same document as a String body (Camel converts it to a SAXSource itself)
transformation result: []
local file contents in the output: false
5) TransformerFactory.newInstance() anywhere in the application
factory: org.apache.camel.quarkus.support.xalan.XalanTransformerFactory
setAttribute(ACCESS_EXTERNAL_DTD, ""): REFUSED, IllegalArgumentException: ...
identity transform of the same document: [... <data>db.password=LOCAL-FILE-s3cr3t-99</data> ...]
Requests the XML parser made to internal endpoints on its own: [GET /internal/secret, GET /internal/leak.dtd]
>>> PROVEN: ...
Camel Quarkus 3.40.0 के विरुद्ध भी सत्यापित: हर लीक करने वाला प्रोब शांत हो जाता है, आंतरिक endpoints
को कोई अनुरोध प्राप्त नहीं होता, और ड्राइवर NOT reproduced प्रिंट करता है।
xslt कंपोनेंट पथ पर, केवल वे bodies प्रभावित हैं जो transformer तक पहले से ही
javax.xml.transform.Source के रूप में पहुँचती हैं। अन्य प्रकार की bodies — String, byte[], InputStream — को
Apache Camel बाहरी entities और बाहरी DTD लोडिंग अक्षम के साथ SAXSource में परिवर्तित करता है, और वे
प्रभावित नहीं हैं। reproducer में प्रोब 4 वह सुरक्षित पथ है, असुरक्षित पथ के साथ-साथ।
चूँकि factory को JAXP डिफ़ॉल्ट के रूप में भी पंजीकृत किया जाता है (support extension
META-INF/services/javax.xml.transform.TransformerFactory भेजता है), एप्लिकेशन में कोई भी अन्य कोड जो
TransformerFactory.newInstance() के माध्यम से factory प्राप्त करता है, बिना किसी त्रुटि के वही प्रतिबंध खो देता है। यही कारण है
कि advisory उन एक्सटेंशनों को सूचीबद्ध करता है जो स्वयं कभी कुछ भी रूपांतरित नहीं करते:
| Extension | Exposure |
|---|---|
camel-quarkus-xslt | the xslt component path and the JAXP default |
camel-quarkus-xslt-saxon | the JAXP default |
camel-quarkus-tika | the JAXP default |
camel-quarkus-xmlsecurity | the JAXP default |
| Property | Value |
|---|---|
| Component | camel-quarkus-support-xalan (XSLT support extension) |
| CWE | CWE-611 (Improper Restriction of XML External Entity Reference) |
| Severity | High |
| Attack vector | An external entity or external DTD declared in the XML document being transformed, where the body reaches the xslt endpoint already as a javax.xml.transform.Source |
| Impact | Read local files; issue requests to internal network locations (SSRF) |
| Affected Versions | From 3.2.0 before 3.33.3, from 3.34.0 before 3.40.0 |
| Fixed Versions | 3.33.3 (LTS stream), 3.40.0 |
| GitHub issue | apache/camel-quarkus#9115 |
| Credit | Discovered by internal analysis, using Claude Security Tool |
Advisory: https://camel.apache.org/security/CVE-2026-88789.html
XalanTransformerFactory अब उन विशेषताओं पर निर्भर रहने के बजाय जिनका Xalan पालन नहीं कर सकता, स्वयं प्रतिबंध लागू करता है:
XMLReader के साथ पार्स किया जाता है जो न बाहरी general और न ही
बाहरी parameter entities को resolve करता है और बाहरी DTDs लोड नहीं करता — वही कॉन्फ़िगरेशन जो Apache Camel का
XmlConverter.createSAXParserFactory() उन bodies के लिए उपयोग करता है जिन्हें camel-xslt स्वयं SAXSource में परिवर्तित करता है।
कॉलर-कॉन्फ़िगर किए गए XMLReader को ले जाने वाले SAXSource का उपयोग वैसे ही किया जाता है, और DOMSource और StAXSource
पहले से ही पार्स किए जा चुके होते हैं।document() फ़ंक्शन द्वारा transform समय पर लाए गए संसाधनों को अस्वीकार कर दिया जाता है जब तक कि एप्लिकेशन का स्वयं का
URIResolver उन्हें resolve न करे, और यह प्रतिबंध हर उस entry point पर स्थापित किया जाता है जो transform करने के लिए कुछ
प्रदान करता है, जिसमें वे SAX push entry points भी शामिल हैं जिनके transformers पर Xalan factory
resolver को कॉपी नहीं करता। जो एप्लिकेशन अपना resolver सेट करते हैं — camel-xslt हर exchange पर ऐसा करता है — वे पहले की तरह
इसे override करते रहते हैं।main पर
9a570b64 और
9dd11779 में ठीक किया गया,
3.33.x में
ad9c5236 और
3d886769 में backport किया गया।
javax.xml.transform.Source को xslt endpoint में पास न करें। संदेश body को
String, byte[] या InputStream के रूप में छोड़ दें ताकि Apache Camel पहले बाहरी entities अक्षम के साथ
इसे SAXSource में परिवर्तित कर दे।Source body पर convertBodyTo कोई workaround नहीं है: वह रूपांतरण उसी factory के माध्यम से
एक identity transform करता है। reproducer में प्रोब 5 वही identity transform है, और यह लीक करता है।com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl का नाम लेकर स्पष्ट रूप से JDK
कार्यान्वयन का अनुरोध करना चाहिए, न कि TransformerFactory.newInstance() पर निर्भर रहना चाहिए। प्रोब 6 वही control है, और यह
पढ़ने से इनकार करता है।यह रिपॉज़िटरी शैक्षिक और रक्षात्मक उद्देश्यों के लिए प्रकाशित की गई है: Apache Camel Quarkus उपयोगकर्ताओं को भेद्यता समझने, यह सत्यापित करने में मदद करने के लिए कि क्या वे प्रभावित हैं, और यह पुष्टि करने के लिए कि अपग्रेड करने से यह हल हो जाती है। इस सामग्री का उपयोग उन सिस्टमों के विरुद्ध न करें जिनके आप स्वामी या संचालक नहीं हैं।