
CVE-2025-68116 का दस्तावेज़ीकरण
लेखक: @x0root
भेद्यता: ब्राउज़र में रेंडर होने योग्य अपलोड्स (SVG / HTML) के माध्यम से स्टोर्ड क्रॉस-साइट स्क्रिप्टिंग (XSS)
प्रभावित सॉफ़्टवेयर: FileRise (< 2.7.1)
पैच किया गया संस्करण: 2.7.1
आधिकारिक CVE (GHSA के माध्यम से अनुरोधित): CVE-2025-68116 (ट्रैकिंग/सलाह: GHSA-35pp-ggh6-c59c)
पिछली संबंधित सलाह (मूल शमन जिसे बायपास किया गया था): GHSA-qrcv-vjvf-fr29
CVSS आकलन:
रिपोर्टर का आकलन आवश्यक विशेषाधिकारों (Privileges Required — PR) का मूल्यांकन शोषण के बिंदु पर करता है, न कि भेद्यता स्थापित करने (planting) के बिंदु पर।
शोषण तब होता है जब कोई पीड़ित उत्पन्न किए गए सार्वजनिक साझा लिंक तक पहुँचता है, जिसके लिए किसी प्रमाणीकरण या विशेषाधिकार की आवश्यकता नहीं होती (PR:N)।
CNA का आकलन PR का मूल्यांकन दुर्भावनापूर्ण फ़ाइल अपलोड करने की क्षमता के आधार पर करता है। हालाँकि, CVSS v3.1 आवश्यक विशेषाधिकारों (PR) को उन विशेषाधिकारों के रूप में परिभाषित करता है जो हमलावर के पास उस समय होने चाहिए जब भेद्यता का शोषण किया जाता है, न कि भेद्य स्थिति को स्थापित करने या तैयार करने के लिए आवश्यक विशेषाधिकार।
इस प्रकार, PR:N वास्तविक-दुनिया की शोषण स्थितियों को अधिक सटीक रूप से दर्शाता है, जिसके परिणामस्वरूप गंभीरता वर्गीकरण Critical (9.6) होता है।
नोट: GHSA-qrcv-vjvf-fr29 ने एक शमन पेश किया था जो SVG को FileRise वेब UI (प्रीव्यू पैन) के अंदर रेंडर होने से रोकता था। यह रिपोर्ट उस शमन के बायपास का दस्तावेजीकरण करती है—विशेष रूप से बैकएंड share/download एंडपॉइंट्स—जिसे GHSA-35pp-ggh6-c59c / CVE-2025-68116 के रूप में ट्रैक किया जाता है।
यह दस्तावेज़ CVE-2025-68116 का एक पूर्ण तकनीकी अभिलेख है: FileRise में एक Stored XSS जो पहले के शमन के बाद भी बना रहा और अंततः v2.7.1 में ठीक किया गया। इसमें खोज (discovery), शोषण proof-of-concepts, बार-बार विफल हुए फिक्स, सटीक root-cause नियंत्रण-प्रवाह विश्लेषण (साक्ष्य के साथ), पैच का अंतिम सत्यापन, और CVSS मूल्यांकन से संबंधित शोषण क्षमता विशेषताओं का विश्लेषण शामिल है। नीचे की सभी सामग्री पुनरुत्पादित परीक्षणों, कंट्रोलर निरीक्षण और सार्वजनिक सलाह थ्रेड पर आधारित है।
पिछली सलाह, GHSA-qrcv-vjvf-fr29, ने FileRise वेब UI में इनलाइन रेंडरिंग को अवरुद्ध करके SVG अपलोड के माध्यम से Stored XSS का समाधान किया था। उस शमन ने यह नहीं संबोधित किया कि बैकएंड एंडपॉइंट्स द्वारा SVG फ़ाइलों को कैसे सर्व किया जाता था, जैसे:
/api/file/download.php/api/file/share.phpCVE-2025-68116 (जिसे GHSA-35pp-ggh6-c59c के रूप में ट्रैक किया जाता है) GHSA-qrcv-vjvf-fr29 शमन के बायपास का दस्तावेजीकरण करता है: एक हमलावर एक क्राफ्टेड SVG संग्रहीत कर सकता है और उसे सार्वजनिक साझा लिंक या कुछ डाउनलोड व्यवहारों के माध्यम से पीड़ितों तक पहुँचा सकता है, जिससे FileRise ऑरिजिन में स्क्रिप्ट निष्पादन होता है।
यह सत्यापित करने के लिए कि क्या बैकएंड अभी भी SVG को रेंडर करने योग्य तरीके से उजागर करता है, मैंने एक सरल PoC SVG अपलोड किया:
फ़ाइल तक पहुँचने पर:
/api/file/download.php?…/api/file/share.php?token=…परिणामस्वरूप alert() निष्पादित हुआ। मूल GHSA-qrcv-vjvf-fr29 शमन (UI प्रीव्यू ब्लॉक) को इन एंडपॉइंट्स तक सीधी पहुँच द्वारा बायपास कर दिया गया।
एक alert() एक PoC है; मैंने पेलोड को आंतरिक APIs के साथ इंटरैक्ट कराकर सार्थक प्रभाव का परीक्षण किया।
उपयोग किया गया परीक्षण पेलोड:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
fetch('/api/upload/upload.php')
.then(response => response.text())
.then(data => alert('API Response: ' + data));
</script>
</svg>
जब एक लॉग-इन व्यवस्थापक ने इस SVG वाले साझा लिंक को खोला, तो स्क्रिप्ट निष्पादित हुई और प्रमाणित API अनुरोध किए। देखे गए प्रभावों में शामिल थे:
{"csrf_expired":true,"csrf_token":"..."})परीक्षण के दौरान प्रदर्शित प्रभाव वर्गीकरण:
मैंने समस्या की सूचना निजी रूप से दी। अनुरक्षक (maintainer) ने कई क्रमिक फिक्स जारी किए:
v2.6.0 → v2.7.0 के दौरान, share लिंक एंडपॉइंट SVG को इस तरह सर्व करता रहा जिससे इनलाइन रेंडरिंग और स्क्रिप्ट निष्पादन संभव हुआ। नीचे दिया गया root cause विश्लेषण बताता है कि पहले के फिक्स इस वेक्टर को पूरी तरह बंद करने में विफल क्यों रहे।
अंतर्निहित कारण कोई एक लापता हेडर नहीं था, बल्कि shareFile() (कंट्रोलर) के अंदर नियंत्रण-प्रवाह और आउटपुट क्रम था, जिसने कई निष्पादन पथों में सुरक्षा हेडर लागू होने से रोका। समस्याओं के दो वर्ग मौजूद थे:
exit; बिंदु जिन्होंने सुरक्षा हेडर सेट होने से पहले ही फ़ंक्शन को छोटा-सर्किट कर दिया।मैंने shareFile() के भीतर readfile() कॉल तक header() और exit; की उपस्थितियों को सूचीबद्ध करने के लिए एक awk स्कैन का उपयोग किया:
कमांड: awk '/function shareFile(/ {flag=1} /readfile(/ {flag=0} flag && /(header|exit;)/ {printf "%4d | %s\n", NR, $0}' src/controllers/FileController.php
देखा गया आउटपुट (मेरे रन से संक्षिप्त):
1649 | header('Content-Type: application/json; charset=utf-8'); 1651 | exit; 1657 | header('Content-Type: application/json; charset=utf-8'); 1659 | exit; 1664 | header('Content-Type: application/json; charset=utf-8'); 1666 | exit; 1670 | header("Content-Type: text/html; charset=utf-8"); 1693 | exit; 1699 | header('Content-Type: application/json; charset=utf-8'); 1701 | exit; 1719 | header('Content-Type: application/json; charset=utf-8'); 1721 | exit; 1725 | header('Content-Type: application/json; charset=utf-8'); 1727 | exit;
सुरक्षा हेडर (हार्डनिंग लॉजिक) लगभग पंक्ति 1743 से शुरू होते हैं:
1743 | header('X-Content-Type-Options: nosniff'); ... 1770 | header("Content-Disposition: attachment; ...");
क्योंकि फ़ंक्शन कई पथों में पहले ही हेडर + exit; उत्सर्जित कर देता है, वे अनुरोध कभी भी हार्डनिंग कोड तक नहीं पहुँचे जो Content-Disposition, nosniff, या प्रतिबंधात्मक प्रकार सेट करता है।
पासवर्ड-संरक्षित share प्रवाह में, फ़ंक्शन ने पासवर्ड प्रॉम्प्ट HTML को पहले ही उत्सर्जित कर दिया:
if (!empty($record['password']) && empty($providedPass)) {
header("Content-Type: text/html; charset=utf-8");
...
exit;
}
यह पथ Content-Type: text/html भेजता है और SVG हार्डनिंग लॉजिक से पहले exit कर जाता है, जिससे उन पासवर्ड-संरक्षित shares में जहाँ कोई पासवर्ड प्रदान नहीं किया गया, ब्राउज़रों में इनलाइन रेंडरिंग होती है।
भेद्यता केवल पासवर्ड-संरक्षित प्रवाहों तक सीमित नहीं थी। मेरे परीक्षणों में एक गैर-पासवर्ड share अनुरोध ने भी text/html लौटाया:
कमांड: curl -svI "http://127.0.0.1:8080/api/file/share.php?token=437d7913884ace4b94fab8ce745a686a" 2>&1 | grep -iE "content-type"
देखा गया: < Content-Type: text/html; charset=UTF-8
यह पुष्टि करता है कि सामान्य (गैर-पासवर्ड) स्थिति में भी प्रतिक्रिया text/html थी, और SVG इनलाइन रेंडर हुआ।
मैंने share एंडपॉइंट का एक रॉ फ़ेच कैप्चर किया जिसमें हेडर हार्डनिंग से पहले उत्सर्जित PHP warnings शामिल थीं। स्नैपशॉट (संक्षिप्त):
कमांड: curl -s "http://127.0.0.1:8080/api/file/share.php?token=437d7913884ace4b94fab8ce745a686a" | head -n 30
देखा गया रॉ आउटपुट (संक्षिप्त):
Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in /data/data/com.termux/files/home/FileRise/src/controllers/FileController.php on line 1644
ये warnings दर्शाती हैं कि हेडर हार्डनिंग से पहले आउटपुट (deprecated notices) उत्पन्न हो गया था, जिससे उन रनों में बाद के header() कॉल्स का प्रभावी होना असंभव हो गया।
nosniff सेट करने वाला हार्डनिंग कोड मौजूद था, लेकिन प्रारंभिक exits और आउटपुट के कारण कई कोड पथों पर वह पहुँचा नहीं गया।Root-cause रिपोर्टों के बाद, अनुरक्षक ने नियंत्रण-प्रवाह और आउटपुट क्रम को संबोधित करने वाले परिवर्तन लागू किए। v2.7.1 में:
exit; बिंदु जो हार्डनिंग को बायपास करते थे, उन्हें सही/संभाला गया।अंतिम सत्यापन (v2.7.1 पर मेरा परीक्षण):
कमांड: curl -svI "http://127.0.0.1:8080/api/file/share.php?token=fc911e48b0a30e9417a9020ef959784d" 2>&1 | grep -iE "content-type|content-disposition"
देखा गया: < Content-Type: application/octet-stream < Content-Disposition: attachment; filename="xss-image.svg"; filename*=UTF-8''xss-image.svg
परिणाम: ब्राउज़र ने डाउनलोड बाध्य किया; SVG इनलाइन नहीं रेंडर हुआ और XSS पेलोड निष्पादित नहीं हुआ। मैं मानता हूँ कि v2.7.1 ने मेरे वातावरण में समस्या का समाधान कर दिया।
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:L — स्कोर: 9.6 (गंभीर)
मैंने यह तर्क सलाह थ्रेड में दर्ज किया और PR:N उपयोग करने का अनुरोध किया।
CNA का CVSS वेक्टर एक सीमित खतरा मॉडल को दर्शाता है।
अनुभवजन्य परीक्षण एक अधिक गंभीर और पुनरुत्पादनीय शोषण पथ प्रदर्शित करता है, जो मानक स्कोरिंग नियमों के अंतर्गत उच्च CVSS 3.1 आधार स्कोर के अनुरूप है।
स्वतंत्र मूल्यांकनकर्ताओं को प्रोत्साहित किया जाता है कि वे इस दस्तावेज़ में वर्णित देखी गई शोषण स्थितियों का उपयोग करके गंभीरता का आकलन करें, यह सुनिश्चित करते हुए कि सार्वजनिक गंभीरता एक संकीर्ण रूप से सीमित आधार रेखा के बजाय वास्तविक-दुनिया के प्रभाव को दर्शाती है।
1649 | header('Content-Type: application/json; charset=utf-8'); 1651 | exit; 1657 | header('Content-Type: application/json; charset=utf-8'); 1659 | exit; 1664 | header('Content-Type: application/json; charset=utf-8'); 1666 | exit; 1670 | header("Content-Type: text/html; charset=utf-8"); 1693 | exit; 1699 | header('Content-Type: application/json; charset=utf-8'); 1701 | exit; 1719 | header('Content-Type: application/json; charset=utf-8'); 1721 | exit; 1725 | header('Content-Type: application/json; charset=utf-8'); 1727 | exit;
सुरक्षा हेडर ~1743 पर शुरू होते हैं: 1743 | header('X-Content-Type-Options: nosniff'); ... 1770 | header("Content-Disposition: attachment; ...");
~/FileRise $ curl -svI "http://127.0.0.1:8080/api/file/share.php?token=437d7913884ace4b94fab8ce745a686a" 2>&1 | grep -iE "content-type" < Content-Type: text/html; charset=UTF-8
Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in /data/data/com.termux/files/home/FileRise/src/controllers/FileController.php on line 1644
...followed by the SVG payload being printed and rendered inline.
~/FileRise $ curl -svI "http://127.0.0.1:8080/api/file/share.php?token=fc911e48b0a30e9417a9020ef959784d" 2>&1 | grep -iE "content-type|content-disposition" < Content-Type: application/octet-stream < Content-Disposition: attachment; filename="xss-image.svg"; filename*=UTF-8''xss-image.svg