扩展程序可以访问浏览器中的特殊权限,因此对攻击者来说很有吸引力。如果扩展程序遭到入侵,该扩展程序的每位用户都会容易受到恶意和不必要的侵入。 请采用以下做法,确保扩展程序安全无虞并保护用户。
保护开发者账号
扩展程序代码通过 Google 账号上传和更新。如果开发者的账号遭到入侵,攻击者可以直接向所有用户推送恶意代码。请启用 双重身份验证(最好使用 安全密钥),保护这些账号。
使用适当的成员角色
如果您的发布商有多个成员,请确保授予每位 用户的角色是适当的。
切勿使用 HTTP
请求或发送数据时,请避免使用 HTTP 连接。假设任何 HTTP 连接都会有窃听者或包含修改。应始终首选 HTTPS,因为它具有内置 安全性,可规避大多数 中间人攻击。
请求最少的权限
Chrome 浏览器会限制扩展程序访问清单中明确请求的权限。扩展程序应仅注册其依赖的 API 和网站,从而最大限度地减少权限。
限制扩展程序的权限可以限制潜在攻击者可以利用的内容。
跨源 fetch()
扩展程序只能使用 fetch() 和 XMLHttpRequest() 从
扩展程序和权限中指定的网域获取资源。请注意,对这两者的调用都会被
Service Worker 中的 fetch 处理程序拦截。
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"host_permissions": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"manifest_version": 3
}
在上面的示例中,此扩展程序通过
在权限中列出 "https://developer.chrome.com/*" 和 "https://*.google.com/*",请求访问 developer.chrome.com 上的任何内容以及 Google 的子网域。如果
扩展程序遭到入侵,它仍然只能与符合
匹配模式的网站互动。攻击者只能有限地访问 "https://user_bank_info.com" 或
与 "https://malicious_website.com" 互动。
限制清单字段
在清单中添加不必要的密钥和权限会造成漏洞,并使扩展程序更容易被发现。请将清单字段限制为扩展程序依赖的字段。
可从外部连接
使用 "externally_connectable" 字段声明扩展程序将与哪些外部扩展程序和网页交换信息。将扩展程序可以从外部连接的对象限制为可信来源。
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"accepts_tls_channel_id": false
},
...
}
可通过 Web 访问的资源
在 "web_accessible_resources" 下使资源可通过 Web 访问,会让
扩展程序能够被网站和攻击者检测到。
{
...
"web_accessible_resources": [
{
"resources": [ "test1.png", "test2.png" ],
"matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
}
]
...
}
可通过 Web 访问的资源越多,潜在攻击者可以利用的途径就越多。请尽可能减少这些文件。
添加明确的内容安全政策
在清单中为扩展程序添加内容安全政策,以防止跨站 脚本攻击。如果扩展程序仅从自身加载资源,请注册以下内容:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "default-src 'self'"
},
"manifest_version": 3
}
如果扩展程序需要使用 Web Assembly 或增加对 沙盒页面 的限制,可以添加以下内容:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
"sandboxed_pages":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
},
"manifest_version": 3
}
避免使用 document.write() 和 innerHTML
虽然使用 document.write() 和 innerHTML 动态创建 HTML 元素可能更简单,但它会让扩展程序及其依赖的网页容易受到攻击,攻击者可以插入恶意脚本。请改为手动创建 DOM 节点,并使用 innerText 插入动态内容。
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
谨慎使用内容脚本
虽然 内容脚本 存在于 隔离的世界 中,但它们并非不受攻击的影响:
- 内容脚本是扩展程序中唯一直接与网页互动的部分。 因此,恶意网页可能会操纵内容脚本依赖的 DOM 部分, 或利用令人意外的 Web 标准行为(例如 命名项)。
- 为了与网页的 DOM 互动,内容脚本需要在与网页相同的渲染器进程中执行。这使得内容脚本容易通过边信道攻击 (例如 Spectre)泄露数据,并且如果恶意网页入侵 渲染器进程,内容脚本可能会被攻击者接管。
使用敏感数据(例如用户的个人信息)或有权访问浏览器功能的 Chrome API 的操作应在扩展程序的 Service Worker 中执行。 避免意外向内容脚本公开扩展程序权限:
- 假设来自内容脚本的消息可能是攻击者精心设计的(例如,验证和清理所有输入,并保护您的脚本免受跨站脚本攻击)。
- 假设发送到内容脚本的任何数据都可能会泄露到网页。请勿向内容脚本发送敏感数据(例如扩展程序的密钥、来自其他 Web 来源的数据、浏览记录)。
- 限制内容脚本可以触发的特权操作的范围。不允许
内容脚本触发对任意网址的请求,也不允许向
扩展程序 API 传递任意实参(例如,不允许向
fetch()或chrome.tabs.create()方法传递任意网址)。
注册并清理输入
通过将监听器限制为仅监听扩展程序预期监听的内容、验证传入数据的发送者以及清理所有输入,保护扩展程序免受恶意脚本的侵害。
如果扩展程序预期会收到来自外部网站或扩展程序的
通信,则应仅注册 runtime.onMessageExternal。请务必验证发送者是否与可信来源匹配。
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
即使是来自扩展程序本身的 runtime.onMessage 事件的消息,也应仔细检查,以 确保 MessageSender 不是来自遭到入侵的 内容脚本。
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});