सामान्य वेब पेज, रिमोट सर्वर से डेटा भेजने और पाने के लिए XMLHttpRequest ऑब्जेक्ट का इस्तेमाल कर सकते हैं. हालांकि, वे एक ही ऑरिजिन की नीति के तहत सीमित होते हैं. कॉन्टेंट स्क्रिप्ट, उस वेब ऑरिजिन की ओर से अनुरोध शुरू करती हैं जिसमें कॉन्टेंट स्क्रिप्ट को डाला गया है. इसलिए, कॉन्टेंट स्क्रिप्ट पर भी एक ही ऑरिजिन की नीति लागू होती है. (कॉन्टेंट स्क्रिप्ट पर CORB, Chrome 73 से और CORS, 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 का इस्तेमाल करने की कोशिश करता है, तो ब्राउज़र इसकी अनुमति नहीं देता. ऐसा तब तक होता है, जब तक एक्सटेंशन ने सही क्रॉस-ऑरिजिन अनुमतियों का अनुरोध न किया हो.
अलग-अलग ऑरिजिन से अनुमतियों का अनुरोध करना
मेनिफ़ेस्ट फ़ाइल के permissions सेक्शन में होस्ट या होस्ट मैच पैटर्न (या दोनों) जोड़कर, एक्सटेंशन अपने ऑरिजिन से बाहर के रिमोट सर्वर का ऐक्सेस मांग सकता है.
{
"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 डायरेक्टिव को साफ़ तौर पर जोड़ते समय सावधानी बरतें.