
CWE-22 Path Traversal in Flask-Uploads 0.2.1 का प्रदर्शन. केवल शैक्षिक और सुरक्षा अनुसंधान उद्देश्यों के लिए. Python 3.11 पर परीक्षण किया गया.
Flask-Uploads संस्करण 0.2.1 में एक गंभीर पथ ट्रैवर्सल भेद्यता मौजूद है। यह लाइब्रेरी अपलोड की गई फ़ाइलों के फ़ाइलनामों को फ़ाइल सिस्टम में सहेजने से पहले ठीक से सैनिटाइज़ करने में विफल रहती है।
विशेष रूप से, flask_uploads.py में save() विधि अपलोड गंतव्य पथ को उपयोगकर्ता द्वारा प्रदान किए गए फ़ाइलनाम के साथ os.path.join() का उपयोग करके सीधे जोड़ती है। यह एक हमलावर को फ़ाइलनाम में निर्देशिका ट्रैवर्सल अनुक्रम (जैसे, ../../) शामिल करने की अनुमति देता है, जिससे वे सर्वर फ़ाइल सिस्टम पर मनमाने स्थानों पर फ़ाइलें लिख सकते हैं।
फ़ाइल: flask_uploads.py (v0.2.1 में पंक्ति 132)
def save(self, storage, filename=None):
if filename is None:
filename = storage.filename
# VULNERABLE CODE: No sanitization of 'filename'
target = os.path.join(self.destination, filename)
storage.save(target)
return filename
एप्लिकेशन डेवलपर पर फ़ाइलनाम को सैनिटाइज़ करने के लिए निर्भर करता है, लेकिन लाइब्रेरी दस्तावेज़ीकरण यह संकेत देता है कि यह फ़ाइल अपलोड को सुरक्षित रूप से संभालता है। डिफ़ॉल्ट रूप से, यदि कोई डेवलपर अनुरोध से कच्चा फ़ाइलनाम पास करता है, तो यह एक भेद्यता की ओर ले जाता है।
ssh_host_key, कॉन्फ़िगरेशन फ़ाइलें) को अधिलेखित कर सकते हैं।.php, .py) को ऐसी निर्देशिका में अपलोड करके जो वेब सर्वर द्वारा निष्पादित की जाती है (जैसे cgi-bin या कोई ज्ञात स्थिर फ़ोल्डर), एक हमलावर सर्वर पर मनमाना कमांड निष्पादित कर सकता है।एक हमलावर एक निर्मित फ़ाइलनाम के साथ POST अनुरोध भेजकर इस भेद्यता का शोषण कर सकता है:
POST /upload HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="../../../../../tmp/pwned.txt"
Content-Type: text/plain
HACKED
------WebKitFormBoundary--
यदि सर्वर इस फ़ाइल को सहेजने के लिए Flask-Uploads का उपयोग करता है, तो यह इच्छित अपलोड निर्देशिका के बजाय /tmp/pwned.txt पर लिखा जाएगा।
लाइब्रेरी को यह सत्यापित करना चाहिए कि जोड़ा गया पथ इच्छित निर्देशिका के अंदर है, os.path.abspath और startswith का उपयोग करके, या हमेशा werkzeug.utils.secure_filename जैसे सैनिटाइज़ेशन फ़ंक्शन का उपयोग करें।
अनुशंसित सुधार:
from werkzeug.utils import secure_filename
# ...
filename = secure_filename(filename)
target = os.path.join(self.destination, filename)