
CVE-2026-39154, CometChat JS SDK में स्टोर्ड XSS
यह निर्देशिका CVE-2026-39154 के पीछे के render sink का एक ईमानदार, स्व-निहित पुनरुत्पादन रखती है: CometChat
JavaScript SDK 3.0.12 में एक संग्रहीत क्रॉस-साइट स्क्रिप्टिंग दोष, जहाँ एक समूह संदेश का data.text फ़ील्ड
अन्य सदस्यों के क्लाइंट में संदर्भ-अनुरूप आउटपुट एन्कोडिंग के बिना रेंडर किया जाता है।
यह पूरी तरह से स्थानीय रूप से सिंथेटिक डेटा के साथ चलता है। यह लाइव CometChat सेवा या किसी तीसरे पक्ष से संपर्क, जाँच या प्रमाणीकरण नहीं करता। यह केवल कमज़ोर क्लाइंट रेंडर पथ का स्थानीय प्रदर्शन है।
मिलान करने वाला PoC रिपॉज़िटरी (writeup में नामित): https://github.com/defineid/Wildfire
Writeup: इस पोर्टफ़ोलियो में writeup-cometchat-xss.html।
| फ़ील्ड | मान |
|---|---|
| CVE | CVE-2026-39154 |
| विक्रेता / उत्पाद | CometChat · JavaScript SDK 3.0.12 |
| वर्ग | संग्रहीत क्रॉस-साइट स्क्रिप्टिंग (CWE-79) |
| एंडपॉइंट | POST /v3.0/messages · इंजेक्शन फ़ील्ड data.text |
| प्राप्तकर्ता | receiverType: group |
| इंटरैक्शन | कोई नहीं; संग्रहीत पेलोड स्वतः निष्पादित होता है जब कोई सदस्य समूह खोलता है |
| प्रकटीकरण | फ़रवरी 2026 में CometChat को रिपोर्ट किया गया (अनुरोध 42660); विक्रेता ने Solved चिह्नित किया; CVE MITRE द्वारा सौंपा गया |
| संदर्भ | https://www.cve.org/CVERecord?id=CVE-2026-39154 |
ठीक किए गए संस्करण पर टिप्पणी: प्रकाशित writeup में कहा गया है कि विक्रेता ने समस्या का समाधान किया ("VENDOR: SOLVED") लेकिन किसी विशिष्ट ठीक किए गए SDK/build संख्या का नाम नहीं देता है, और ऊपर दिए गए CVE रिकॉर्ड के अलावा कोई अलग विक्रेता advisory URL नहीं दिया गया है। यहाँ कोई ठीक किया गया संस्करण संख्या नहीं बताई गई है क्योंकि writeup इसे प्रदान नहीं करता है।
एक CometChat TextMessage अपना टेक्स्ट data.text में रखता है, जो UI कोड के लिए
message.getText() के रूप में उजागर होता है। एक प्रमाणीकृत सदस्य किसी समूह को एक ऐसा संदेश भेज सकता है जिसका
data.text HTML मार्कअप शामिल करता है, उदाहरण के लिए:
POST /v3.0/messages
{
"receiverType": "group",
"receiver": "<groupId>",
"category": "message",
"type": "text",
"data": { "text": "" }
}
प्लेटफ़ॉर्म उस स्ट्रिंग को जैसा है वैसा ही संग्रहीत करता है। जब कोई भी समूह सदस्य
बातचीत खोलता है, तो क्लाइंट का संदेश-सूची रेंडर पथ data.text लेता है और उसे
DOM में HTML के रूप में, बिना प्रासंगिक आउटपुट एन्कोडिंग के डालता है (एक innerHTML-शैली
लेखन, न कि textContent लेखन)। इसलिए `` मार्कअप पार्स किया जाता है;
इसका src=x लोड होने में विफल रहता है, जिससे onerror हैंडलर सक्रिय होता है, और हमलावर की
स्क्रिप्ट पीड़ित के सत्र में चलती है। चूँकि संदेश संग्रहीत है, यह स्थायी है और समूह को देखने के अलावा
पीड़ित के किसी हस्तक्षेप की आवश्यकता नहीं है।
प्रकट किया गया फ़िक्स इस फ़ील्ड को सैनिटाइज़ / प्रासंगिक रूप से एन्कोड करता है, इसलिए वही इनपुट निष्पादित होने के बजाय निष्क्रिय टेक्स्ट के रूप में रेंडर होता है।
एक प्रमाणित समूह सदस्य हमलावर है; पीड़ित उस समूह के अन्य सदस्य हैं। पेलोड एक बार वितरित किया जाता है, सर्वर-साइड संग्रहीत किया जाता है, और जब भी कोई सदस्य बातचीत देखता है तो यह स्वचालित रूप से उसके ब्राउज़र में निष्पादित होता है। किसी क्लिक, अनुमति अनुदान, या अतिरिक्त हस्तक्षेप की आवश्यकता नहीं है। मूल रिपोर्ट में प्रभाव: प्रत्येक सदस्य के सत्र में मनमाना स्क्रिप्ट निष्पादन (सत्र/टोकन चोरी, पीड़ित की ओर से क्रियाएँ, बातचीत डेटा का खुलासा)।
repro.html — एक सादा स्थानीय पृष्ठ (सादा सफ़ेद, न्यूनतम CSS, एक सरल संदेश-सूची
क्षेत्र) जो केवल कमज़ोर SDK 3.0.12 रेंडर पथ का प्रतिनिधित्व करता है। इसमें
बिना सैनिटाइज़ किए गए सिंक की एक विश्वसनीय स्थानीय प्रति है:
function getText(message){ return message.data.text; } // mirrors TextMessage#getText()
...
body.innerHTML = getText(message); // *** the SDK 3.0.12 sink, reproduced ***
यह उस सिंक के माध्यम से एक सिंथेटिक संग्रहीत-संदेश ऑब्जेक्ट को रेंडर करता है ताकि इंजेक्ट किया गया स्क्रिप्ट स्थानीय रूप से निष्पादित हो। पृष्ठ पर एक इनलाइन ईमानदार नोट बताता है कि यह SDK 3.0.12 सिंक का स्थानीय पुनरुत्पादन है, कि फ़िक्स्ड SDK फ़ील्ड को सैनिटाइज़ करता है, और यह कि इसमें कोई लाइव CometChat सेवा शामिल नहीं है।
payload.json — सिंथेटिक संग्रहीत TextMessage ऑब्जेक्ट। इसका data.text फ़ील्ड
इंजेक्शन बिंदु है (_injection_point / _note कुंजियों के साथ एनोटेट, क्योंकि
JSON में टिप्पणियाँ नहीं होतीं)। इंजेक्शन वेक्टर (``)
प्रकट रिपोर्ट के समान है; क्रिया को एक हानिरहित इन-पेज
मार्कर में बदल दिया गया है।
payload.txt — वही इंजेक्शन सादे टेक्स्ट में प्रलेखित, जिसमें मूल तैयार किया गया
अनुरोध शामिल है, इस स्पष्ट नोट के साथ कि यह कहीं भेजा नहीं जाता।
यह repro.html राइटअप में दिए गए तंत्र से लिखा गया एक न्यूनतम स्टैंड-इन है।
यह विक्रेता के स्रोत कोड का अंश नहीं है; इस पुनरुत्पादन के लिए वास्तविक SDK प्राप्त
या डिसअसेंबल नहीं किया गया था।
इस रीप्रो में पेलोड हानिरहित है: alert(document.domain) के बजाय,
onerror हैंडलर window.__xss_fired = true सेट करता है, पृष्ठ में RESULT: XSS-FIRED लिखता है,
और दस्तावेज़ का शीर्षक सेट करता है। कुछ भी एक्सफ़िल्ट्रेट नहीं किया जाता।
cd poc/CVE-2026-39154
python3 -m http.server 5599
# then open http://localhost:5599/repro.html in a browser
repro.html संग्रहीत संदेश की एक एम्बेडेड प्रति को समकालिक रूप से रेंडर करता है (ताकि
headless कैप्चर के अंतर्गत भी sink नियतात्मक रूप से सक्रिय हो) और इसके अतिरिक्त
payload.json को फ़ेच करता है ताकि यह पुष्टि हो सके कि डिस्क पर मौजूद आर्टिफ़ैक्ट लोड होता है और वही फ़ील्ड रखता है।
RESULT: XSS-FIRED दिखाता है — यह प्रमाण है कि
इंजेक्ट किया गया onerror स्क्रिप्ट अनसैनिटाइज़्ड innerHTML sink के माध्यम से निष्पादित हुआ।data.text एन्कोड किया जाएगा और
शाब्दिक टेक्स्ट `` के रूप में दिखाई देगा, बिना किसी स्क्रिप्ट निष्पादन के।payload.json
को सुगठित JSON के रूप में मान्य किया गया और पुष्टि की गई कि यह
data.text में इंजेक्शन ले जाता है (एक वेक्टर)। निर्देशिका को `python3 -m http.server 5599` के साथ सर्व किया गया, और `repro.html` को **Firefox 140.11.0esr headless** में `--screenshot` के माध्यम से लोड किया गया (यहाँ `repro-screenshot.png` के रूप में सहेजा गया)। कैप्चर किए गए स्क्रीनशॉट में एक टूटे-छवि तत्व के रूप में रेंडर होता दिखता है (अर्थात् data.text को HTML के रूप में पार्स किया गया,
टेक्स्ट के रूप में नहीं दिखाया गया) और DOM में RESULT: XSS-FIRED लिखा हुआ है। यह पुष्टि करता है
कि अनसैनिटाइज़्ड innerHTML sink संदेश फ़ील्ड से इंजेक्ट की गई स्क्रिप्ट निष्पादित करता है।/v3.0/messages पर कुछ भी नहीं भेजा गया, कोई खाता या
समूह उपयोग नहीं किया गया, और कोई वास्तविक SDK बिल्ड डाउनलोड, निष्पादित या डिसअसेंबल नहीं किया गया।
यहाँ sink, writeup में वर्णित तंत्र पर आधारित एक निष्ठापूर्ण हस्तलिखित स्टैंड-इन है,
विक्रेता का शिप किया गया कोड नहीं। सटीक फ़िक्स किए गए SDK संस्करण की पुष्टि नहीं की गई क्योंकि writeup में कोई संस्करण नहीं बताया गया है।यह एक स्थानीय, ऑफ़लाइन पुनरुत्पादन है जो केवल कृत्रिम, स्वयं-उत्पन्न डेटा का उपयोग करता है, और इसे पहले से रिपोर्ट किए गए और विक्रेता द्वारा समाधान किए गए CVE का दस्तावेज़ीकरण करने के लिए बनाया गया है। यह कमज़ोर रेंडर पथ के स्थानीय स्टैंड-इन को लक्षित करता है, किसी लाइव या तृतीय-पक्ष सिस्टम को नहीं। पेलोड एक हानिरहित इन-पेज मार्कर है; इसमें यह प्रदर्शित करने से अधिक कोई डेटा-चोरी या हथियारीकरण नहीं है कि फ़ील्ड अनसैनिटाइज़्ड रूप में रेंडर होता है।