
सुरक्षा सलाह: एजेंट संदेशों के माध्यम से संग्रहीत क्रॉस-साइट स्क्रिप्टिंग जिससे सत्र टोकन की चोरी होती है (openclaw-dashboard)
शीर्षक: OpenClaw डैशबोर्ड में lastMessage सत्र फ़ील्ड के माध्यम से संग्रहीत XSS CVE आईडी: CVE-2026-66421
https://github.com/tugcantopaloglu/openclaw-dashboard
डैशबोर्ड के लैंडिंग पृष्ठ पर सत्र तालिका प्रत्येक एजेंट सत्र का अंतिम संदेश दिखाती है। वह पाठ एजेंट के वार्तालाप ट्रांसक्रिप्ट से लिया जाता है और बिना किसी एस्केपिंग के innerHTML के साथ पृष्ठ में लिखा जाता है। OpenClaw एक मल्टी-चैनल एजेंट गेटवे है, इसलिए संदेश पाठ किसी ऐसे व्यक्ति से आ सकता है जो एजेंट से बात करने में सक्षम है, जैसे कि चैट समूह या वेबहुक। HTML पेलोड वाला संदेश एडमिनिस्ट्रेटर के ब्राउज़र में स्क्रिप्ट के रूप में चलता है, जैसे ही वे डैशबोर्ड खोलते हैं।
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:Nपहली सार्वजनिक रिलीज़ से मौजूद है। यह कमजोर रेंडर सबसे पुराने टैग (v1.1.0) और वर्तमान main (d6198d0) तक के प्रत्येक बाद के कमिट में मौजूद है। लिखे जाने के समय इसे ठीक नहीं किया गया है।
हमलावर वह पक्ष है जो एजेंट के सत्र ट्रांसक्रिप्ट तक पहुंचने वाला संदेश भेज सकता है। उन्हें डैशबोर्ड खाते की आवश्यकता नहीं होती। एक विशिष्ट OpenClaw तैनाती में, इसमें जुड़े चैट चैनलों के सदस्य और कोई भी स्रोत शामिल होता है जो वेबहुक के माध्यम से एजेंट तक पहुंचता है, इसलिए हमलावर अक्सर ऑपरेटर की विश्वास सीमा के बाहर होता है।
पेलोड ट्रांसक्रिप्ट में संग्रहीत होता है और जब भी एडमिनिस्ट्रेटर सत्र पृष्ठ देखता है तो रेंडर हो जाता है। वह पृष्ठ डिफ़ॉल्ट लैंडिंग दृश्य है और टाइमर पर रीफ्रेश होता है, इसलिए आवश्यक एकमात्र इंटरैक्शन यह है कि एडमिनिस्ट्रेटर अपने सामान्य डैशबोर्ड को लोड करे। AT:P उस एक शर्त को दर्शाता है जिस पर हमलावर निर्भर करता है: कि तैनाती उनके संदेशों को उस सत्र में रूट करती है जिसे डैशबोर्ड प्रदर्शित करता है।
चरण 1. संदेश पाठ ट्रांसक्रिप्ट से निकाला जाता है। सर्वर सबसे हालिया संदेश पढ़ता है और उसका पाठ, जो 80 अक्षरों तक काटा गया है, बिना किसी सैनिटाइज़ेशन के लौटाता है:
// server.js:474-481
if (typeof msg.content === 'string') {
text = msg.content;
} else if (Array.isArray(msg.content)) {
for (const b of msg.content) {
if (b.type === 'text' && b.text) { text = b.text; break; }
}
}
if (text) return text.replace(/\n/g, ' ').substring(0, 80);
चरण 2. यह सत्र API के माध्यम से उजागर होता है। getSessionsJson पाठ को प्रत्येक सत्र के lastMessage फ़ील्ड पर रखता है:
// server.js:538
lastMessage: getLastMessage(s.sessionId || key),
GET /api/sessions इस ऐरे को ब्राउज़र को लौटाता है।
चरण 3. इसे बिना एस्केपिंग के DOM में लिखा जाता है। सत्र तालिका प्रत्येक पंक्ति को स्ट्रिंग संयोजन द्वारा बनाती है और उसे innerHTML से असाइन करती है:
// index.html:3758
const lastMsg = s.lastMessage ? s.lastMessage.substring(0, 60) + (s.lastMessage.length > 60 ? '…' : '') : '';
// index.html:3773
<div class="table-cell" style="..." onclick="toggleSessionExpand('${escapedKey}', event)">${lastMsg}</div>
lastMsg को सीधे HTML स्ट्रिंग में रखा जाता है। इस पथ पर कहीं भी कोई एन्कोडिंग चरण नहीं है।
यही तालिका s.label (index.html:3770) और s.key (index.html:3767) को उसी तरह पंक्ति मार्कअप में इंटरपोलेट करती है। उन फ़ील्ड्स पर कोई 60-अक्षर सीमा नहीं है, इसलिए वे उस हमलावर को पेलोड के लिए अधिक जगह देते हैं जो उन्हें प्रभावित कर सकता है।
server.js:298 पर Content-Security-Policy इनलाइन इवेंट हैंडलर्स (script-src 'self' 'unsafe-inline') की अनुमति देता है, इसलिए एक onerror हैंडलर चलता है।
एजेंट को संदेश भेजने में सक्षम पक्ष के रूप में, एक ऐसा संदेश भेजें जिसका पाठ 60-अक्षर बजट में फिट होने वाला छोटा पेलोड हो, उदाहरण के लिए:
यह 56 अक्षरों का है और किसी भी सामान्य संदेश की तरह एजेंट के सत्र ट्रांसक्रिप्ट तक पहुंचता है।
पुष्टि करें कि सर्वर पेलोड को बिना एस्केप किए लौटाता है:
curl -H "Authorization: Bearer ADMIN_TOKEN" http://TARGET:7000/api/sessions
प्रभावित सत्र के lastMessage फ़ील्ड में कच्ची `` स्ट्रिंग होती है।
एडमिनिस्ट्रेटर डैशबोर्ड खोलता है। सत्र पृष्ठ डिफ़ॉल्ट दृश्य है, इसलिए किसी अतिरिक्त नेविगेशन की आवश्यकता नहीं होती। पंक्ति रेंडर होती है, ब्राउज़र `` टैग पार्स करता है, onerror हैंडलर चलता है, और एडमिनिस्ट्रेटर का सत्र टोकन पेलोड द्वारा पढ़ लिया जाता है।
console.log बॉडी को किसी same-origin प्रमाणित एंडपॉइंट पर fetch से बदलने से पेलोड लॉग इन उपयोगकर्ता के विशेषाधिकारों के साथ कार्य कर सकता है।
लॉग इन उपयोगकर्ता के रूप में डैशबोर्ड ओरिजिन में स्क्रिप्ट निष्पादन, जो किसी ऐसे व्यक्ति के लिए सुलभ है जिसे केवल एजेंट को संदेश भेजने की आवश्यकता है। पेलोड सत्र टोकन पढ़ सकता है और प्रमाणित एंडपॉइंट्स को कॉल कर सकता है, जिसमें वे भी शामिल हैं जो एजेंट की अपनी निर्देश फ़ाइलों और OpenClaw कॉन्फ़िगरेशन को संपादित करते हैं। चूंकि यह डिफ़ॉल्ट पृष्ठ पर ट्रिगर होता है, एडमिनिस्ट्रेटर को कोई असामान्य कार्रवाई नहीं करनी पड़ती।
lastMessage, label और key को HTML-एन्कोड करें, या HTML स्ट्रिंग के बजाय textContent का उपयोग करके सेल बनाएं।innerHTML के माध्यम से रेंडर होने वाले अन्य सत्र फ़ील्ड्स पर भी लागू करें।script-src से 'unsafe-inline' हटा दें ताकि इंजेक्ट किया गया मार्कअप तब भी निष्पादित न हो सके जब कोई एन्कोडिंग चरण छूट जाए।