क्रॉस-ऑरिजिन XMLHttpRequest

रेगुलर वेब पेज, रिमोट सर्वर से डेटा भेजने और पाने के लिए XMLHttpRequest ऑब्जेक्ट का इस्तेमाल कर सकते हैं, लेकिन उन पर एक ही ऑरिजिन नीति लागू होती है. कॉन्टेंट स्क्रिप्ट, उस वेब ऑरिजिन की ओर से अनुरोध करती है जिसमें कॉन्टेंट स्क्रिप्ट को इंजेक्ट किया गया है. इसलिए, कॉन्टेंट स्क्रिप्ट पर भी एक जैसी ऑरिजिन नीति लागू होती है. (कॉन्टेंट स्क्रिप्ट, Chrome 73 के बाद से CORB और Chrome 83 के बाद से सीओआरएस पर निर्भर करती हैं.) एक्सटेंशन के ऑरिजिन बहुत सीमित नहीं हैं - किसी एक्सटेंशन के बैकग्राउंड पेज या फ़ोरग्राउंड टैब पर काम करने वाली स्क्रिप्ट, अपने ऑरिजिन से बाहर के रिमोट सर्वर से तब तक इंटरैक्ट कर सकती है, जब तक एक्सटेंशन क्रॉस-ऑरिजिन अनुमतियों का अनुरोध करता है.

एक्सटेंशन ऑरिजिन

चल रहा हर एक्सटेंशन, अपने अलग सुरक्षा ऑरिजिन में मौजूद होता है. अतिरिक्त खास अधिकारों का अनुरोध किए बिना, एक्सटेंशन अपने इंस्टॉलेशन के दौरान संसाधनों को पाने के लिए XMLHttpRequest का इस्तेमाल कर सकता है. उदाहरण के लिए, अगर किसी एक्सटेंशन में config.json नाम की JSON कॉन्फ़िगरेशन फ़ाइल मौजूद है, तो config_resources फ़ोल्डर में एक्सटेंशन, फ़ाइल का कॉन्टेंट इस तरह से फ़ेच कर सकता है:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();

अगर एक्सटेंशन, https://www.google.com जैसे किसी सुरक्षा ऑरिजिन का इस्तेमाल करने की कोशिश करता है, तो ब्राउज़र उसे तब तक अनुमति नहीं देता, जब तक एक्सटेंशन सही क्रॉस-ऑरिजिन अनुमतियों का अनुरोध नहीं करता.

क्रॉस-ऑरिजिन अनुमतियों का अनुरोध करना

मेनिफ़ेस्ट फ़ाइल के अनुमतियां सेक्शन में, होस्ट या होस्ट मैच पैटर्न (या दोनों) जोड़कर, एक्सटेंशन अपने ऑरिजिन से बाहर के रिमोट सर्वर के ऐक्सेस का अनुरोध कर सकता है.

{
  "name": "My extension",
  ...
  "permissions": [
    "https://www.google.com/"
  ],
  ...
}

क्रॉस-ऑरिजिन अनुमति की वैल्यू, पूरी तरह क्वालिफ़ाइड होस्ट नाम हो सकते हैं, जैसे कि:

  • "https://www.google.com/"
  • "https://www.gmail.com/"

या वे मिलान पैटर्न हो सकते हैं, जैसे:

  • "https://*.google.com/"
  • "https://*/"

"https://*/" से मैच होने वाले पैटर्न से, सभी ऐक्सेस किए जा सकने वाले डोमेन के लिए एचटीटीपीएस का ऐक्सेस मिलता है. ध्यान दें कि यहां, मैच पैटर्न, कॉन्टेंट स्क्रिप्ट से मैच होने वाले पैटर्न से मिलते-जुलते होते हैं. हालांकि, होस्ट के बाद दी गई पाथ की जानकारी को अनदेखा कर दिया जाता है.

यह भी ध्यान रखें कि ऐक्सेस, होस्ट और स्कीम, दोनों से मिला है. अगर कोई एक्सटेंशन किसी होस्ट या होस्ट के सेट के लिए, सुरक्षित और असुरक्षित, दोनों एचटीटीपी ऐक्सेस चाहता है, तो उसे अनुमतियों के बारे में अलग से एलान करना होगा:

"permissions": [
  "http://www.google.com/",
  "https://www.google.com/"
]

सुरक्षा से जुड़ी बातें

क्रॉस-साइट स्क्रिप्टिंग जोखिम की आशंकाओं से बचना

XMLHttpRequest से मिले संसाधनों का इस्तेमाल करते समय, आपके बैकग्राउंड पेज पर इस बात का ध्यान रखना चाहिए कि क्रॉस-साइट स्क्रिप्टिंग का शिकार न हो. खास तौर पर, खतरनाक एपीआई का इस्तेमाल करने से बचें. जैसे:

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // WARNING! Might be evaluating an evil script!
    var resp = eval("(" + xhr.responseText + ")");
    ...
  }
}
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // WARNING! Might be injecting a malicious script!
    document.getElementById("resp").innerHTML = xhr.responseText;
    ...
  }
}
xhr.send();

इसके बजाय, उन सुरक्षित एपीआई को प्राथमिकता दें जो स्क्रिप्ट नहीं चलाते:

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // JSON.parse does not evaluate the attacker's scripts.
    var resp = JSON.parse(xhr.responseText);
  }
}
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    // innerText does not let the attacker inject HTML elements.
    document.getElementById("resp").innerText = xhr.responseText;
  }
}
xhr.send();

क्रॉस-ऑरिजिन अनुरोधों तक कॉन्टेंट के स्क्रिप्ट ऐक्सेस को सीमित करना

किसी कॉन्टेंट स्क्रिप्ट की ओर से क्रॉस-ऑरिजिन अनुरोध करते समय, ऐसे नुकसान पहुंचाने वाले वेब पेजों से सावधान रहें जो किसी कॉन्टेंट स्क्रिप्ट की नकल करके, किसी दूसरे कॉन्टेंट की स्क्रिप्ट तैयार कर सकते हैं. खास तौर पर, कॉन्टेंट स्क्रिप्ट को किसी आर्बिट्ररी यूआरएल का अनुरोध करने की अनुमति न दें.

एक ऐसा उदाहरण देखें जिसमें कोई एक्सटेंशन क्रॉस-ऑरिजिन अनुरोध करता है, ताकि कॉन्टेंट स्क्रिप्ट किसी आइटम की कीमत पता कर सके. एक (असुरक्षित) तरीका यह है कि कॉन्टेंट स्क्रिप्ट में वह सटीक संसाधन बताया जाए जिसे बैकग्राउंड पेज से फ़ेच किया जा सके.

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
      if (request.contentScriptQuery == 'fetchUrl') {
        // WARNING: SECURITY PROBLEM - a malicious web page may abuse
        // the message handler to get access to arbitrary cross-origin
        // resources.
        fetch(request.url)
            .then(response => response.text())
            .then(text => sendResponse(text))
            .catch(error => ...)
        return true;  // Will respond asynchronously.
      }
    });
chrome.runtime.sendMessage(
    {contentScriptQuery: 'fetchUrl',
     url: 'https://another-site.com/price-query?itemId=' +
              encodeURIComponent(request.itemId)},
    response => parsePrice(response.text()));

ऊपर बताए गए तरीके में, कॉन्टेंट स्क्रिप्ट एक्सटेंशन से ऐसे किसी भी यूआरएल को फ़ेच करने का अनुरोध कर सकती है जिसका ऐक्सेस एक्सटेंशन के पास हो. नुकसान पहुंचाने वाला वेब पेज, ऐसे मैसेज बना सकता है और एक्सटेंशन को धोखे से क्रॉस-ऑरिजिन रिसॉर्स का ऐक्सेस दे सकता है.

इसके बजाय, ऐसे मैसेज हैंडलर डिज़ाइन करें जो फ़ेच किए जा सकने वाले रिसॉर्स को सीमित करते हैं. नीचे, सिर्फ़ itemId कॉन्टेंट स्क्रिप्ट से मिला है, पूरा यूआरएल नहीं.

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
      if (request.contentScriptQuery == 'queryPrice') {
        var url = 'https://another-site.com/price-query?itemId=' +
            encodeURIComponent(request.itemId);
        fetch(url)
            .then(response => response.text())
            .then(text => parsePrice(text))
            .then(price => sendResponse(price))
            .catch(error => ...)
        return true;  // Will respond asynchronously.
      }
    });
chrome.runtime.sendMessage(
    {contentScriptQuery: 'queryPrice', itemId: 12345},
    price => ...);

एचटीटीपी के बजाय एचटीटीपीएस को प्राथमिकता देना

इसके अलावा, एचटीटीपी से वापस मिले संसाधनों पर खास तौर से ध्यान दें. अगर आपके एक्सटेंशन का इस्तेमाल किसी विरोधी नेटवर्क पर किया जाता है, तो नेटवर्क हमलावर (यानी "man-in-the-middle") जवाब में बदलाव कर सकता है और आपके एक्सटेंशन पर हमला कर सकता है. इसके बजाय, जहां भी हो सके वहां एचटीटीपीएस को प्राथमिकता दें.

कॉन्टेंट की सुरक्षा नीति में बदलाव करना

अपने मेनिफ़ेस्ट में content_security_policy एट्रिब्यूट जोड़कर, ऐप्लिकेशन या एक्सटेंशन के लिए डिफ़ॉल्ट कॉन्टेंट की सुरक्षा नीति में बदलाव करने पर, आपको यह पक्का करना होगा कि जिन होस्ट से कनेक्ट करना है उन्हें अनुमति दी गई हो. डिफ़ॉल्ट नीति, होस्ट से कनेक्ट करने पर पाबंदी नहीं लगाती है. हालांकि, connect-src या default-src डायरेक्टिव को साफ़ तौर पर जोड़ते समय सावधानी बरतें.