一般網頁可以使用 XMLHttpRequest 物件,從遠端傳送及接收資料 但受到相同來源政策的限制。內容指令碼發出要求 也就是內容指令碼中所插入的網頁來源;因此 指令碼也適用相同的來源政策。(內容指令碼已受到 CORB 規範 Chrome 73 以上版本和 CORS (自 Chrome 83 版本以來皆支援))。擴充功能來源不是如此有限 - 指令碼 在擴充功能的背景頁面或前景分頁執行時,可以與 只要擴充功能要求跨來源權限即可。
擴充功能來源
每個執行中的擴充功能都存在於各自的安全性來源中。無須要求額外的
權限,擴充功能可以使用 XMLHttpRequest 取得安裝項目中的資源。適用對象
例如,如果擴充功能在config.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://*/」的比對模式允許 HTTPS 存取所有可連線的網域。請注意,這裡的比對 模式與內容指令碼比對模式類似,但是在 系統會忽略主機。
另請注意,存取權是由主機和配置授予。如果擴充功能需要 存取指定主機或一組主機的不安全 HTTP 存取時,必須個別宣告這些權限:
"permissions": [
"http://www.google.com/",
"https://www.google.com/"
]
安全性考量
避免跨網站指令碼攻擊漏洞
使用透過 XMLHttpRequest 擷取的資源時,您的背景頁面應謹慎處理 導致跨網站指令碼攻擊成為受害者。具體來說,請避免使用危險的 API,例如 如下:
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();
請改為使用不會執行指令碼的更安全的 API:
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 => ...);
使用 HTTPS 而非 HTTP
此外,透過 HTTP 擷取資源時請格外小心。如果擴充功能用於 惡意網路,網路攻擊者 (又稱"man-in-the-middle") 可能會修改回應 也許可以攻擊你的擴充功能請盡可能改用 HTTPS。
調整內容安全政策
如果您修改了應用程式或擴充功能的預設「內容安全政策」,
將 content_security_policy
屬性加入資訊清單,您必須確保
,允許連線你的設定檔。雖然預設政策不會限制與主機的連線
明確加入 connect-src
或 default-src
指令時,請務必小心。