DOM-आधारित क्रॉस-साइट स्क्रिप्टिंग (DOM XSS) तब होती है, जब उपयोगकर्ता के ज़रिए कंट्रोल किए जाने वाले सोर्स (जैसे कि उपयोगकर्ता नाम या यूआरएल फ़्रैगमेंट से लिया गया रीडायरेक्ट यूआरएल) का डेटा, सिंक में पहुंचता है. यह eval()
जैसा फ़ंक्शन या .innerHTML
जैसा कोई प्रॉपर्टी सेटर है, जो आर्बिट्रेरी JavaScript कोड को लागू कर सकता है.
DOM XSS सबसे सामान्य वेब सुरक्षा जोखिमों में से एक है और डेवलपर टीम के लिए यह सामान्य है कि वे उसे अपने ऐप्लिकेशन में गलती से उपलब्ध करा दें. भरोसेमंद टाइप से आपको लिखने, सुरक्षा की समीक्षा करने, और ऐप्लिकेशन को DOM XSS के खतरों से बचाने में मदद मिलती है. ये टूल, नुकसान पहुंचाने वाले वेब एपीआई फ़ंक्शन को डिफ़ॉल्ट रूप से सुरक्षित बनाते हैं. भरोसेमंद टाइप, उन ब्राउज़र के लिए polyfill के तौर पर उपलब्ध होते हैं जो फ़िलहाल काम नहीं करते.
बैकग्राउंड
कई सालों से DOM XSS, वेब सुरक्षा से जुड़े सबसे प्रचलित और खतरनाक जोखिमों में से एक रहा है.
क्रॉस-साइट स्क्रिप्टिंग दो तरह की होती हैं. कुछ XSS जोखिम की आशंका सर्वर-साइड कोड की वजह से होती है, जो वेबसाइट बनाने वाला एचटीएमएल कोड असुरक्षित तरीके से बना देता है. वहीं, कुछ दूसरी समस्याओं की असल वजह क्लाइंट पर है, जहां JavaScript कोड ऐसी खतरनाक सुविधाओं को उपयोगकर्ता के कंट्रोल किए जाने वाले कॉन्टेंट के साथ कॉल करता है.
सर्वर-साइड XSS को रोकने के लिए, स्ट्रिंग को जोड़कर एचटीएमएल जनरेट न करें. इसके बजाय, कॉन्टेक्स्ट के हिसाब से ऑटोएस्कैपिंग की सुविधा का इस्तेमाल करें. साथ ही, गड़बड़ियों को कम करने के लिए, कॉन्टेंट की सुरक्षा से जुड़ी नीति का भी इस्तेमाल करें.
अब ब्राउज़र भरोसेमंद टाइप का इस्तेमाल करके, क्लाइंट-साइड DOM पर आधारित XSS को रोकने में भी मदद कर सकते हैं.
एपीआई के बारे में जानकारी
भरोसेमंद प्रकार, नीचे दिए गए जोखिम भरे सिंक फ़ंक्शन को लॉक करके काम करते हैं. इनमें से कुछ सुविधाओं को शायद आप पहले ही पहचान लें, क्योंकि ब्राउज़र वेंडर और वेब फ़्रेमवर्क पहले से ही सुरक्षा वजहों से आपको इन सुविधाओं का इस्तेमाल करने से रोकते हैं.
- स्क्रिप्ट में बदलाव करना:
<script src>
<script>
एलिमेंट का टेक्स्ट कॉन्टेंट सेट करना. - किसी स्ट्रिंग से एचटीएमएल जनरेट करना:
- प्लगिन कॉन्टेंट को एक्ज़ीक्यूट करना:
- रनटाइम में JavaScript कोड को कंपाइल करना:
eval
setTimeout
setInterval
new Function()
भरोसेमंद प्रकार के लिए यह ज़रूरी है कि इन सिंक फ़ंक्शन को डेटा भेजने से पहले आप उसे प्रोसेस करें. सिर्फ़ स्ट्रिंग का इस्तेमाल नहीं किया जा सकता, क्योंकि ब्राउज़र को यह पता नहीं चलता कि डेटा भरोसेमंद है या नहीं:
anElement.innerHTML = location.href;
यह बताने के लिए कि डेटा सुरक्षित तरीके से प्रोसेस किया गया था, एक खास ऑब्जेक्ट बनाएं - एक भरोसेमंद टाइप.
anElement.innerHTML = aTrustedHTML;
भरोसेमंद टाइप की मदद से, आपके ऐप्लिकेशन के DOM XSS हमले की सतह को काफ़ी कम किया जा सकता है. यह सुरक्षा समीक्षाओं को सरल बनाता है. साथ ही, आपको ब्राउज़र में रनटाइम के दौरान, अपने कोड को कंपाइल, लिंटिंग या बंडल करते समय, टाइप पर आधारित सुरक्षा जांच लागू करने देता है.
भरोसेमंद टाइप इस्तेमाल करने का तरीका
कॉन्टेंट की सुरक्षा के बारे में नीति के उल्लंघन की रिपोर्ट तैयार करना
आपके पास रिपोर्ट कलेक्टर, जैसे कि ओपन-सोर्स go-csp-collector को इस्तेमाल करने का विकल्प होता है. इसके अलावा, रिपोर्ट कलेक्टर को इस्तेमाल करने के लिए भी इसका इस्तेमाल किया जा सकता है. ब्राउज़र में, उल्लंघनों को डीबग भी किया जा सकता है:
document.addEventListener('securitypolicyviolation',
console.error.bind(console));
सिर्फ़ रिपोर्ट वाला सीएसपी हेडर जोड़ें
जिन दस्तावेज़ों को भरोसेमंद टाइप पर माइग्रेट करना है उनके लिए, यहां दिया गया एचटीटीपी रिस्पॉन्स हेडर जोड़ें:
Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example
अब सभी उल्लंघनों की रिपोर्ट //my-csp-endpoint.example
की रिपोर्ट की जाती है, लेकिन
वेबसाइट अब भी काम कर रही है. अगले सेक्शन में बताया गया है कि
//my-csp-endpoint.example
कैसे काम करता है.
भरोसेमंद तरह के उल्लंघनों की पहचान करना
अब से, जब भी भरोसेमंद टाइप को किसी उल्लंघन का पता चलता है, तब ब्राउज़र कॉन्फ़िगर किए गए report-uri
को एक रिपोर्ट भेजता है. उदाहरण के लिए, जब आपका ऐप्लिकेशन
innerHTML
को एक स्ट्रिंग पास करता है, तब ब्राउज़र यह रिपोर्ट भेजता है:
{
"csp-report": {
"document-uri": "https://my.url.example",
"violated-directive": "require-trusted-types-for",
"disposition": "report",
"blocked-uri": "trusted-types-sink",
"line-number": 39,
"column-number": 12,
"source-file": "https://my.url.example/script.js",
"status-code": 0,
"script-sample": "Element innerHTML <img src=x"
}
}
इसका मतलब है कि लाइन 39 पर https://my.url.example/script.js
में, innerHTML
को <img src=x
से शुरू होने वाली स्ट्रिंग के साथ कॉल किया गया. इस जानकारी से आपको यह समझने में मदद मिलेगी कि कोड के कौनसे हिस्से DOM XSS का इस्तेमाल कर रहे हैं और आपको उनमें बदलाव करने की ज़रूरत है.
उल्लंघन ठीक करें
भरोसेमंद टाइप की नीति के उल्लंघन को ठीक करने के लिए, कुछ विकल्प दिए गए हैं. आपके पास आपत्तिजनक कोड हटाने, लाइब्रेरी का इस्तेमाल करने, भरोसेमंद टाइप की नीति बनाने या आखिरी सुझाव के तौर पर, डिफ़ॉल्ट नीति बनाने का विकल्प होता है.
उल्लंघन करने वाला कोड फिर से लिखें
ऐसा हो सकता है कि अब उस कोड की ज़रूरत न हो जो नियमों का पालन न करता हो या उसे उन फ़ंक्शन के बिना फिर से लिखा जा सकता हो जो उल्लंघन करते हैं:
el.textContent = ''; const img = document.createElement('img'); img.src = 'xyz.jpg'; el.appendChild(img);
el.innerHTML = '';
लाइब्रेरी का इस्तेमाल करना
कुछ लाइब्रेरी पहले से ही भरोसेमंद प्रकार जनरेट करती हैं जिन्हें आप सिंक फ़ंक्शन में भेज सकते हैं. उदाहरण के लिए, XSS पेलोड को हटाकर, एचटीएमएल स्निपेट को साफ़ करने के लिए DOMPurify का इस्तेमाल किया जा सकता है.
import DOMPurify from 'dompurify';
el.innerHTML = DOMPurify.sanitize(html, {RETURN_TRUSTED_TYPE: true});
DOMPurify भरोसेमंद टाइप के साथ काम करता है. यह TrustedHTML
ऑब्जेक्ट में रैप किए गए सैनिटाइज़ एचटीएमएल को दिखाता है, ताकि ब्राउज़र कोई उल्लंघन न करे.
भरोसेमंद टाइप की नीति बनाएं
कभी-कभी उल्लंघन करने वाला कोड नहीं हटाया जा सकता और वैल्यू को साफ़ करने और आपके लिए'भरोसेमंद टाइप' बनाने के लिए कोई लाइब्रेरी नहीं होती. ऐसे मामलों में, आपके पास खुद ही एक भरोसेमंद टाइप ऑब्जेक्ट बनाने का विकल्प होता है.
सबसे पहले, एक नीति बनाएं. नीतियां, 'भरोसेमंद टाइप' के लिए फ़ैक्ट्री होती हैं जो अपने इनपुट पर कुछ सुरक्षा नियम लागू करती हैं:
if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
const escapeHTMLPolicy = trustedTypes.createPolicy('myEscapePolicy', {
createHTML: string => string.replace(/\</g, '<')
});
}
यह कोड, myEscapePolicy
नाम की नीति बनाता है. यह अपने createHTML()
फ़ंक्शन का इस्तेमाल करके, TrustedHTML
ऑब्जेक्ट बना सकता है. तय किए गए नियम, HTML-एस्केप <
वर्णों को नए एचटीएमएल एलिमेंट के बनने से रोकने के लिए हैं.
नीति का इस्तेमाल इस तरह करें:
const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML); // true
el.innerHTML = escaped; // '<img src=x onerror=alert(1)>'
डिफ़ॉल्ट नीति का इस्तेमाल करें
कभी-कभी आपत्तिजनक कोड को नहीं बदला जा सकता. उदाहरण के लिए, अगर सीडीएन से तीसरे पक्ष की कोई लाइब्रेरी लोड की जा रही हो. इस स्थिति में, किसी डिफ़ॉल्ट नीति का इस्तेमाल करें:
if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
trustedTypes.createPolicy('default', {
createHTML: (string, sink) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true})
});
}
default
नाम की नीति का इस्तेमाल हर उस जगह पर किया जाता है जहां सिंक में मौजूद स्ट्रिंग का इस्तेमाल सिर्फ़ ऐसे सिंक में किया जाता है जो सिर्फ़ भरोसेमंद टाइप के लिए स्वीकार करता है.
कॉन्टेंट की सुरक्षा के बारे में नीति लागू करने के लिए स्विच करें
जब आपका ऐप्लिकेशन उल्लंघन नहीं करता, तो भरोसेमंद टाइप के नियम लागू किए जा सकते हैं:
Content-Security-Policy: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example
अब, चाहे आपका वेब ऐप्लिकेशन कितना भी जटिल क्यों न हो, आपकी नीति में मौजूद कोड सिर्फ़ एक DOM XSS जोखिम पेश कर सकता है. और आप नीति बनाने को सीमित करके तक सीमित करके इसे और भी ज़्यादा लॉक कर सकते हैं.