
Security Advisory: Unauthenticated Path Traversal Allows Arbitrary File Read (TinyWeb)
निर्धारित CVE ID: CVE-2026-67185
TinyWeb वेब रूट को अनुरोध URL के साथ जोड़कर सर्विस की जाने वाली फ़ाइल का पाथ इस प्रकार बनाता है जैसे वह आता है, बिना किसी नॉर्मलाइज़ेशन के। एक दूरस्थ क्लाइंट जिसने कभी प्रमाणीकरण नहीं किया है, वह अनुरोध लाइन में ../ अनुक्रम सम्मिलित कर सकता है और सर्वर प्रक्रिया द्वारा खोली जा सकने वाली किसी भी फ़ाइल को पढ़ सकता है, जिसमें वेब रूट के बाहर की फ़ाइलें भी शामिल हैं।
TnyWeb/0.0.80b3b5fd (2019-01-09), जहां पाथ पहली बार इस तरह जोड़ा गया था, से लेकर a381da2 (2023-11-22, master पर नवीनतम) तक।CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:Nएक अनधिकृत दूरस्थ हमलावर जो सर्वर के सुनने वाले TCP पोर्ट (भेजे गए कॉन्फ़िगरेशन में 9090) तक पहुंच सकता है। कोई क्रेडेंशियल, कोई उपयोगकर्ता इंटरैक्शन, और किसी पूर्व पहुंच की आवश्यकता नहीं है। एक एकल अनुरोध पर्याप्त है।
HttpBuilder::buildResponse() कॉन्फ़िगर किए गए वेब रूट से शुरू होता है और पार्स किए गए अनुरोध से सीधे URL पाथ फ़ील्ड को जोड़ता है:
// src/tiny_http/http_responser.cc:80
sdsncat(&file_path, server.www.c_str(), server.www.size());
// src/tiny_http/http_responser.cc:83-87
if (url->field_set & (1 << HTTP_UF_PATH)) {
unsigned int off = url->fields[HTTP_UF_PATH].offset;
unsigned int len = url->fields[HTTP_UF_PATH].len;
sdsncat(&file_path, url->data + off, len);
}
// src/tiny_http/http_responser.cc:90-94
std::string f(file_path.data, file_path.len);
file_type = isRegularFile(f);
if (0 == file_type) {
return_val = file->setFile(f); // stat() + open() on the joined path
}
लाइन 86 पर जोड़ने और लाइन 94 पर फाइलसिस्टम कॉल के बीच कोई डॉट-सेगमेंट हटाना (RFC 3986 सेक्शन 5.2.4), कोई realpath() कैननिकलाइज़ेशन, और यह जांच नहीं है कि परिणाम server.www के अंदर रहता है।
URL पार्सर .. को भी फ़िल्टर नहीं करता है। HttpParser::parseUrlChar() में पाथ स्टेट किसी भी ऐसे कैरेक्टर को स्वीकार करता है जो isUrlChar() को पास करता है, और . एक मान्य URL कैरेक्टर है, इसलिए ../ बिना बदले buildResponse() तक पहुंचता है:
// src/tiny_http/http_parser.cc:653-654
case s_requ_path: //finished
if (isUrlChar(ch))
return s_requ_path;
HttpFile::setFile() फिर उत्पादित किसी भी पाथ को खोलता है और सर्व करता है, सर्वर प्रक्रिया के विशेषाधिकारों का उपयोग करते हुए:
// src/tiny_http/http_model_file.cc:43
return_val = open(name.c_str(), O_RDONLY);
नोट: TinyWeb URL पाथ को कभी भी प्रतिशत-डिकोड नहीं करता है, इसलिए %2e%2e%2f काम नहीं करता है। शाब्दिक ../ रूप काम करता है।
सर्वर को भेजे गए कॉन्फ़िगरेशन के साथ शुरू करें (पोर्ट 9090 पर सुनना, कॉन्फ़िगर किए गए वेब रूट से सर्व करना)।
एक अनुरोध भेजें जिसका पाथ वेब रूट से ऊपर चढ़ता है। --path-as-is फ़्लैग curl को भेजने से पहले ../ को समेटने से रोकता है:
curl --path-as-is 'http://TARGET:9090/../../../../etc/passwd'
/etc/passwd की सामग्री के साथ 200 OK प्रतिक्रिया देता है:HTTP/1.1 200 OK
Server: TinyWeb/0.0.8
Transfer-Encoding: chunked
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
आवश्यक ../ सेगमेंट की संख्या इस बात पर निर्भर करती है कि वेब रूट कितनी गहराई पर स्थित है। वेब रूट की गहराई के बराबर या उससे अधिक कोई भी गिनती काम करती है, क्योंकि कर्नेल फाइलसिस्टम रूट पर .. को अनदेखा करता है।
कोई भी दूरस्थ क्लाइंट उस किसी भी फ़ाइल को पढ़ सकता है जिसे सर्वर प्रक्रिया खोलने की अनुमति रखती है। डिफ़ॉल्ट सेटअप में वर्कर्स रूट के रूप में चलते हैं, इसलिए इसमें /etc/shadow, TLS निजी कुंजियाँ, क्रेडेंशियल वाली कॉन्फ़िगरेशन फ़ाइलें, और वेब रूट के अंतर्गत एप्लिकेशन का अपना सोर्स शामिल है।
realpath() के साथ जोड़े गए पाथ को कैननिकलाइज़ करें और जब तक परिणाम कॉन्फ़िगर किए गए वेब रूट के अंदर न हो, अनुरोध को अस्वीकार करें। डिफेंस इन डेप्थ के रूप में, RFC 3986 सेक्शन 5.2.4 के अनुसार URL पार्सिंग के दौरान डॉट-सेगमेंट हटाएँ, और उस नॉर्मलाइज़ेशन को चलाने से पहले पाथ को प्रतिशत-डिकोड करें।