
परामर्श: CVE-2026-38361 dash-uploader (Python/PyPI) में कई DoS कमजोरियाँ (CWE-400/CWE-670)
fohrloop/dash-uploader (Python, PyPI) में कई बिना प्रमाणीकरण वाली डिनायल ऑफ़ सर्विस (DoS) समस्याएँ हैं, जिनमें (केवल यही नहीं) आउट-ऑफ़-मेमोरी (OOM) प्रोसेस क्रैश, फ़ाइल का शून्य बाइट्स में ट्रंकेशन, स्थायी डिस्क क्षरण और दस्तावेज़ित max_file_size सीमा का पूर्ण बायपास शामिल है। उसी बिना सैनिटाइज़ किए गए पैरामीटर सेट के माध्यम से अतिरिक्त संसाधन-दुरुपयोग पथ भी मौजूद हैं।
रिपॉज़िटरी को बिना किसी सक्रिय अनुरक्षक के 2025-07-19 को संग्रहीत किया गया था। प्रकाशित हर संस्करण (0.1.0 से 0.7.0a2 तक) प्रभावित है और रहेगा। पैकेज अभी भी लगभग 28,000 मासिक डाउनलोड प्राप्त करता है।
प्रोडक्शन में dash-uploader चलाने वाले किसी भी व्यक्ति को स्वयं शमन (mitigation) लागू करना होगा। अनुशंसित समाधान Plotly Dash के अंतर्निहित dcc.Upload घटक पर माइग्रेट करना है। पूर्ण विकल्पों के लिए शमन देखें।
| CVE ID | CVE-2026-38361 (NVD) |
| भेद्यता | अनियंत्रित संसाधन खपत (CWE-400), हमेशा-गलत नियंत्रण प्रवाह कार्यान्वयन (CWE-670) |
| CVSS 3.1 | 7.5 / उच्च (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) |
| उत्पाद | dash-uploader |
| प्रभावित संस्करण | 0.1.0 से 0.7.0a2 तक (सभी 18 रिलीज़) |
| फिक्स्ड संस्करण | कोई नहीं (प्रोजेक्ट 2025-07-19 को संग्रहीत) |
| आक्रमण वेक्टर | दूरस्थ, बिना प्रमाणीकरण |
| खोजकर्ता | Muhammad Fitri Bin Mohd Sultan |
| निर्धारक | MITRE, 2026-05-07 |
| संबंधित | CVE-2026-38360 (उसी लाइब्रेरी में पाथ ट्रैवर्सल) |
dash-uploader HTTP हैंडलर बिना प्रमाणीकरण वाले POST अनुरोधों को स्वीकार करता है, जिनमें हमलावर-नियंत्रित पैरामीटर मेमोरी आवंटन, फ़ाइल संचालन और निर्देशिका निर्माण में प्रवाहित होते हैं, बिना किसी बाउंड जाँच, बिना दर सीमा और बिना किसी सफाई तंत्र के। उसी कोड पथ में चार स्वतंत्र समस्याएँ हैं:
7.7 GB सिस्टम पर सत्यापित: resumableTotalChunks=30000000 वाले 5 समवर्ती POST अनुरोधों ने 2 सेकंड के भीतर Linux OOM किलर को सक्रिय कर दिया। कर्नेल लॉग पुष्टि करता है:
Out of memory: Killed process 24203 (python3) total-vm:8302276kB, anon-rss:7068012kB
प्रत्येक अनुरोध range(1, resumableTotalChunks + 1) पर लिस्ट कॉम्प्रिहेंशन के माध्यम से लगभग 2.9 GB मेमोरी आवंटित करता है। सर्वर प्रोसेस समाप्त कर दिया जाता है और मैन्युअल पुनःआरंभ तक एप्लिकेशन पूरी तरह अनुपलब्ध हो जाता है।
42 बाइट्स डेटा वाली एक फ़ाइल को resumableTotalChunks=0 वाले एक एकल POST अनुरोध के माध्यम से 0 बाइट्स तक कम कर दिया गया। मूल कारण यह है कि Python का all() खाली इटरेबल्स के लिए True लौटाता है, जो अपलोड हैंडलर को शून्य चंक्स को पूर्ण अपलोड मानने में धोखा देता है। मौजूदा फ़ाइल को os.unlink() के माध्यम से हटा दिया जाता है और एक खाली फ़ाइल से बदल दिया जाता है।
चंक फ़ाइलों वाली 10 अनाथ अस्थायी निर्देशिकाएँ बनाई गईं और डिस्क पर अनिश्चित काल तक बनी रहीं। सभी स्रोत फ़ाइलों में cleanup, ttl, expire, garbage, purge, cron, schedule और periodic के लिए कोडबेस-व्यापी खोज में शून्य परिणाम मिले। एकमात्र सफाई कॉल (shutil.rmtree) केवल पूर्ण अपलोड पर निष्पादित होती है। अधूरे सत्रों से डिस्क स्थान पुनः प्राप्त करने का कोई तंत्र नहीं है।
max_file_size बायपास (सत्यापित)सर्वर ने HTTP 200 के साथ resumableTotalSize=999999999999 (~999 GB) का दावा करने वाली फ़ाइल के लिए 5 MB चंक स्वीकार किया। max_file_size पैरामीटर केवल React JavaScript घटक को भेजा जाता है। सर्वर कभी भी फ़ाइल आकार, चंक आकार, Content-Length या Flask MAX_CONTENT_LENGTH की जाँच नहीं करता। max_file_size=10 सेट करने वाले डेवलपर के पास कोई सर्वर-साइड सुरक्षा नहीं है।
# dash_uploader/httprequesthandler.py
def _post(self):
resumableTotalChunks = request.form.get("resumableTotalChunks", type=int) # attacker-controlled, no bounds
...
chunk_paths = [
os.path.join(temp_dir, get_chunk_name(resumableFilename, x))
for x in range(1, resumableTotalChunks + 1) # unbounded; e.g. 30M -> ~2.9 GB -> OOM
]
upload_complete = all([os.path.exists(p) for p in chunk_paths]) # all([]) is True -> truncation when chunks=0
if upload_complete:
target_file_name = os.path.join(temp_root, resumableFilename)
if os.path.exists(target_file_name):
os.unlink(target_file_name) # existing file deleted
with open(target_file_name, "ab") as target_file:
for p in chunk_paths: # empty list -> empty file written
...
समान कोड पथ OOM (बड़ा resumableTotalChunks) और फ़ाइल-ट्रंकेशन प्रिमिटिव (resumableTotalChunks=0) दोनों उत्पन्न करता है।
एक हमलावर /API/resumable एंडपॉइंट पर बिना प्रमाणीकरण वाले POST अनुरोध भेजता है।
resumableTotalChunks=30000000 वाले 5 समवर्ती अनुरोध प्रत्येक ~2.9 GB आवंटित करते हैं, जिससे OOM किलर सक्रिय हो जाता है।resumableTotalChunks=0 भेजें; Python all([])=True सर्वर को लक्षित फ़ाइल को खाली सामग्री से अधिलेखित करने में धोखा देता है।कोई प्रमाणीकरण या विशेषाधिकार आवश्यक नहीं है।
resumableTotalChunks) से असीमित मेमोरी आवंटन द्वारा ट्रिगर Linux OOM किलर के माध्यम से सर्वर प्रोसेस क्रैशresumableIdentifier के साथ os.makedirs() के माध्यम से मनमानी गहराई की निर्देशिका निर्माण द्वारा फ़ाइलसिस्टम inode क्षरणresumableTotalChunks=0 हो, तो खाली इटरेबल्स के लिए Python all() का True लौटाना फ़ाइल के शून्य बाइट्स में ट्रंकेशन के माध्यम से डेटा विनाश का कारण बनता हैmax_file_size केवल क्लाइंट-साइड JavaScript में लागू होता है, जबकि सर्वर-साइड हैंडलर कोई आकार सत्यापन नहीं करता और कभी Flask MAX_CONTENT_LENGTH सेट नहीं करताdash_uploader/httprequesthandler.py (BaseHttpRequestHandler._post विधि)dash_uploader/upload.py (Upload फ़ंक्शन, max_file_size पैरामीटर)dash_uploader/configure_upload.py (MAX_CONTENT_LENGTH अनुपलब्ध)वर्तमान में तैनात उपयोगकर्ताओं के लिए विकल्प, प्राथमिकता के क्रम में:
dcc.Upload पर माइग्रेट करें, यह Plotly Dash के साथ आधिकारिक रूप से आने वाला अपलोड घटक है। इसमें कोई चंक-गणना पैरामीटर नहीं है, कोई डिस्क-पर अस्थायी स्थिति नहीं है, और यह Flask MAX_CONTENT_LENGTH का सम्मान करता है। यहाँ की चारों समस्याओं में से कोई भी लागू नहीं होती। यह छोटी और मध्यम फ़ाइलों के लिए सर्वोत्तम है। बहुत बड़े अपलोड के लिए, आइटम 2 देखें।MAX_CONTENT_LENGTH), क्लाइंट-आपूर्ति चंक गणना पर सीमाएँ, और स्वीकृत फ़ाइलनामों के लिए एक अनुमत-सूची (allowlist) हो।MAX_CONTENT_LENGTH सेट करें (लाइब्रेरी नहीं करती), और एप्लिकेशन या रिवर्स-प्रॉक्सी परत पर इनपुट अस्वीकार करें जहाँ निम्न में से कोई भी सत्य हो:
resumableTotalChunks <= 0resumableTotalChunks उचित सीमा से अधिक हो (जैसे, 10,000)resumableTotalSize डेवलपर-कॉन्फ़िगर किए गए max_file_size से अधिक हो| दिनांक | घटना |
|---|---|
| 2026-03-19 | प्रोडक्शन तैनाती पर सुरक्षा अनुसंधान के दौरान भेद्यताएँ खोजी गईं। |
| 2026-03-22 | MITRE को CVE अनुरोध प्रस्तुत किया गया। |
| 2026-05-07 | CVE-2026-38361 MITRE द्वारा निर्धारित किया गया। |
| 2026-05-07 | सार्वजनिक एडवाइज़री प्रकाशित की गई। |
| 2026-05-09 | CVE रिकॉर्ड MITRE CVE डेटाबेस और NVD पर प्रकाशित किया गया। |
0.6.1 (स्थिर श्रृंखला)। प्री-रिलीज़ 0.7.0a2 तक विस्तृत हैं।dash। वैकल्पिक निर्भरता: pyyaml। लाइसेंस: MIT।Muhammad Fitri Bin Mohd Sultan