'भरोसेमंद टाइप' की मदद से, DOM-आधारित क्रॉस-साइट स्क्रिप्टिंग के जोखिमों को रोकें

Krzysztof Kotowicz
Krzysztof Kotowicz

ब्राउज़र सहायता

  • 83
  • 83
  • x
  • x

सोर्स

DOM पर आधारित क्रॉस-साइट स्क्रिप्टिंग (DOM XSS) तब होती है, जब उपयोगकर्ता के कंट्रोल वाले सोर्स (जैसे कि उपयोगकर्ता नाम या यूआरएल फ़्रैगमेंट से लिया गया रीडायरेक्ट यूआरएल) का डेटा सिंक तक पहुंचता है. यह eval() या .innerHTML जैसा प्रॉपर्टी सेटर होता है, जो आर्बिट्रेरी JavaScript कोड चला सकता है.

DOM XSS सबसे सामान्य वेब सुरक्षा कमज़ोरियों में से एक है और डेवलपर टीमों के लिए अपने ऐप्लिकेशन में गलती से उन्हें लागू करना आम बात है. भरोसेमंद टाइप में, खतरनाक वेब एपीआई फ़ंक्शन को डिफ़ॉल्ट रूप से सुरक्षित बनाकर, लिखने और सुरक्षा की समीक्षा करने के टूल मिलते हैं. साथ ही, इनसे ऐप्लिकेशन को DOM XSS के जोखिम से बचाया जा सकता है. भरोसेमंद टाइप, उन ब्राउज़र के लिए polyfill के तौर पर उपलब्ध हैं जो फ़िलहाल उनके लिए काम नहीं करते हैं.

बैकग्राउंड

कई सालों से DOM XSS वेब सुरक्षा से जुड़े सबसे आम और खतरनाक जोखिमों में से एक रहा है.

क्रॉस-साइट स्क्रिप्टिंग दो तरह की होती हैं. कुछ XSS जोखिम की आशंकाएं सर्वर-साइड कोड की वजह से होती हैं जो असुरक्षित तरीके से वेबसाइट बनाने वाला एचटीएमएल कोड बना देता है. वहीं, दूसरी वजहों से क्लाइंट को मिले डेटा की कोई असल वजह होती है, क्योंकि JavaScript कोड उपयोगकर्ता को कंट्रोल करने वाले कॉन्टेंट के साथ खतरनाक फ़ंक्शन का पता लगाता है.

सर्वर-साइड XSS को रोकने के लिए, स्ट्रिंग को जोड़कर एचटीएमएल जनरेट न करें. इसके बजाय, लाइब्रेरी के टेंप्लेट के बजाय, कॉन्टेक्स्ट के हिसाब से अपने-आप होने वाली प्रोसेस के लिए सुरक्षा से जुड़ी नीति का इस्तेमाल करें. साथ ही, गड़बड़ियों को कम करने के लिए नॉन्स के हिसाब से कॉन्टेंट की सुरक्षा के बारे में नीति का इस्तेमाल करें.

ब्राउज़र, अब भरोसेमंद टाइप का इस्तेमाल करके, क्लाइंट-साइड DOM पर आधारित XSS को रोकने में भी मदद कर सकते हैं.

एपीआई के बारे में जानकारी

ट्रस्टेड टाइप नीचे दिए गए जोखिम वाले सिंक फ़ंक्शन को लॉक करके काम करते हैं. शायद आपने इनमें से कुछ साइटों को पहले से ही पहचान लिया हो, क्योंकि सुरक्षा की वजहों से, ब्राउज़र वेंडर और वेब फ़्रेमवर्क आपको पहले से ही इन सुविधाओं का इस्तेमाल करने से दूर रखते हैं.

भरोसेमंद टाइप के लिए ज़रूरी है कि आप डेटा को इन सिंक फ़ंक्शन में पास करने से पहले उसे प्रोसेस करें. सिर्फ़ स्ट्रिंग का इस्तेमाल नहीं किया जा सकता, क्योंकि ब्राउज़र को यह पता नहीं चलता कि डेटा भरोसेमंद है या नहीं:

ऐसा न करें
anElement.innerHTML  = location.href;
भरोसेमंद टाइप के चालू होने पर, ब्राउज़र एक TypeError दिखाता है और स्ट्रिंग के साथ DOM XSS सिंक के इस्तेमाल को रोकता है.

डेटा को सुरक्षित तरीके से प्रोसेस किया गया, यह बताने के लिए एक खास ऑब्जेक्ट बनाएं - भरोसेमंद टाइप.

ऐसा करें
anElement.innerHTML = aTrustedHTML;
  
'भरोसेमंद टाइप' के चालू होने पर, ब्राउज़र सिंक के लिए TrustedHTML ऑब्जेक्ट स्वीकार करता है. यह ऑब्जेक्ट, एचटीएमएल स्निपेट के लिए होता है. अन्य संवेदनशील सिंक के लिए भी TrustedScript और TrustedScriptURL ऑब्जेक्ट मौजूद हैं.

ट्रस्टेड टाइप, आपके ऐप्लिकेशन के DOM XSS अटैक सरफ़ेस को काफ़ी कम कर देते हैं. यह सुरक्षा समीक्षाओं को आसान बनाता है. साथ ही, ब्राउज़र में रनटाइम के दौरान आपके कोड को कंपाइल, लिंट या बंडल करते समय, टाइप के हिसाब से की जाने वाली सुरक्षा जांचों को लागू करने देता है.

विश्वसनीय प्रकार का इस्तेमाल कैसे करें

कॉन्टेंट की सुरक्षा के बारे में नीति के उल्लंघन की रिपोर्ट तैयार करना

आपके पास रिपोर्ट कलेक्टर को डिप्लॉय करने का विकल्प होता है. जैसे, ओपन-सोर्स reporting-api-processor या go-csp-collector. इसके अलावा, आपके पास किसी ऐसी कंपनी के व्यावसायिक इस्तेमाल का इस्तेमाल करने का भी विकल्प है. आप ReportingObserver का इस्तेमाल करके ब्राउज़र में कस्टम लॉगिंग और डीबग उल्लंघन को भी जोड़ सकते हैं:

const observer = new ReportingObserver((reports, observer) => {
    for (const report of reports) {
        if (report.type !== 'csp-violation' ||
            report.body.effectiveDirective !== 'require-trusted-types-for') {
            continue;
        }

        const violation = report.body;
        console.log('Trusted Types Violation:', violation);

        // ... (rest of your logging and reporting logic)
    }
}, { buffered: true });

observer.observe();

या कोई इवेंट लिसनर जोड़कर:

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"
}
}

इसका मतलब है कि https://my.url.example/script.js में, लाइन 39 में, innerHTML को <img src=x से शुरू होने वाली स्ट्रिंग से कॉल किया गया था. इस जानकारी से आपको यह तय करने में मदद मिलती है कि कोड के कौनसे हिस्से, DOM XSS की शुरुआत कर सकते हैं और उन्हें बदलने की ज़रूरत है.

उल्लंघन ठीक करें

भरोसेमंद टाइप के उल्लंघन को ठीक करने के कई विकल्प हैं. इसके लिए, आपत्तिजनक कोड को हटाया जा सकता है, लाइब्रेरी का इस्तेमाल किया जा सकता है, भरोसेमंद टाइप से जुड़ी नीति बनाई जा सकती है या आखिरी सुझाव के तौर पर, डिफ़ॉल्ट नीति बनाई जा सकती है.

आपत्तिजनक कोड को फिर से लिखें

ऐसा हो सकता है कि अब नॉन-कंफ़ॉर्मिंग कोड की ज़रूरत न रही हो या उसे उल्लंघन करने वाले फ़ंक्शन के बिना दोबारा लिखा जा सकता हो:

ऐसा करें
el.textContent = '';
const img = document.createElement('img');
img.src = 'xyz.jpg';
el.appendChild(img);
ऐसा न करें
el.innerHTML = '<img src=xyz.jpg>';

लाइब्रेरी का इस्तेमाल करना

कुछ लाइब्रेरी पहले से ही ऐसे भरोसेमंद टाइप जनरेट करती हैं जिन्हें आप सिंक फ़ंक्शन में पास कर सकते हैं. उदाहरण के लिए, 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, '&lt;')
  });
}

यह कोड, myEscapePolicy नाम की नीति बनाता है. यह अपने createHTML() फ़ंक्शन का इस्तेमाल करके, TrustedHTML ऑब्जेक्ट बना सकता है. तय किए गए नियमों में HTML-escape < वर्णों का इस्तेमाल करके, नए एचटीएमएल एलिमेंट को बनाने से रोका जाता है.

नीति का इस्तेमाल इस तरह करें:

const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML);  // true
el.innerHTML = escaped;  // '&lt;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 के जोखिम की आशंका पैदा कर सकता है. नीति बनाने पर पाबंदी लगाकर उसे और भी ज़्यादा लॉक किया जा सकता है.

इसके बारे में और पढ़ें