Stay secure(保持安全)

扩展程序可以访问浏览器中的特殊权限,这使它们成为攻击者的有吸引力的目标。如果某个扩展程序遭到破坏,该扩展程序的每个用户都容易受到恶意和不需要的入侵。通过结合这些做法,确保扩展安全并保护其用户。

# Protect developer accounts(保护开发者帐号)

扩展代码通过 Google 帐户上传和更新。如果开发人员的帐户被盗用,攻击者可以将恶意代码直接推送给所有用户。通过创建专门的开发人员帐户并启用双因素身份验证(最好使用安全密钥)来保护这些帐户。

# Keep groups selective(保持组的选择性)

如果使用群组发布,请将群组限制为受信任的开发人员。不接受不明人士的入会申请。

# 永远不要使用 HTTP,永远(Never use HTTP, Ever)

请求或发送数据时,避免 HTTP 连接。假设任何 HTTP 连接都会有窃听者或包含修改。 HTTPS 应该始终是首选,因为它具有内置的安全性,可以规避大多数中间人攻击(man-in-the-middle attacks)。

# Request minimal permissions(请求最低权限)

Chrome 浏览器会限制扩展程序对清单中明确请求的权限的访问。扩展程序应该通过仅注册它们依赖的 API 和网站来最小化它们的权限。应尽量减少任意代码。

限制扩展权限限制了潜在攻击者可以利用的内容。

# Cross-origin XMLHttpRequest(跨域)

扩展只能使用 XMLHttpRequest 从自身和权限中指定的域获取资源。

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "permissions": [
    "https://developer.chrome.com/*",
    "https://*.google.com/*"
  ],
  "manifest_version": 2
}

此扩展程序通过在权限中列出“https://developer.chrome.com/”和“`https://.google.com/*”来请求访问 developer.chrome.com 和 Google 子域上的任何内容。如果扩展程序遭到破坏,它仍然只能与符合[匹配模式](./match_patterns.md)的网站进行交互。攻击者将无法访问“https://user_bank_info.com`”或与“`https://malicious_website.com`”交互。

# Limit manifest fields(限制清单字段)

在清单中包含不必要的注册会产生漏洞并使扩展更加明显。将清单字段限制为扩展所依赖的字段并提供特定字段注册。

# Externally connectable(可外接)

使用 externally_connectable 字段声明扩展将与哪些外部扩展和网页交换信息。限制扩展程序可以从外部连接到受信任来源的人员。

{
  "name": "Super Safe Extension",
  "externally_connectable": {
    "ids": [
      "iamafriendlyextensionhereisdatas"
    ],
    "matches": [
      "https://developer.chrome.com/*",
      "https://*.google.com/*"
    ],
    "accepts_tls_channel_id": false
  },
  ...
}

# Web-accessible resources(可通过网络访问的资源)

使网络可访问资源,在 web_accessible_resources 下将使网站和攻击者可检测到扩展。

{
  ...
  "web_accessible_resources": [
    "images/*.png",
    "style/secure_extension.css",
    "script/secure_extension.js"
  ],
  ...
}

可用的 Web 可访问资源越多,潜在攻击者可以利用的途径就越多。将这些文件保持在最低限度。

# Include an explicit content security policy(包括明确的内容安全策略)

在清单中包含扩展的内容安全策略content security policy,以防止跨站点脚本攻击。如果扩展仅从自身加载资源,请注册以下内容:

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "content_security_policy": "default-src 'self'; frame-ancestors 'none';",
  "manifest_version": 2
}

如果扩展需要包含来自特定主机的脚本,则可以包含它们:

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "content_security_policy": "default-src 'self' https://extension.resource.com; frame-ancestors 'none';",
  "manifest_version": 2
}

# Avoid executable APIs(避免可执行的 API)

执行代码的 API 应该替换为更安全的替代方案。

# document.write() and innerHTML

虽然使用 document.write()innerHTML 动态创建 HTML 元素可能更简单,但它会使扩展以及扩展所依赖的网页对插入恶意脚本的攻击者开放。相反,手动创建 DOM 节点并使用 innerText 插入动态内容。

function constructDOM() {
  let newTitle = document.createElement('h1');
  newTitle.innerText = host;
  document.appendChild(newTitle);
}

# eval()

尽可能避免使用 eval() 以防止攻击,因为 eval() 将执行传入它的任何代码,这可能是恶意的。

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();

相反,更喜欢更安全、更快的方法,例如 JSON.parse()

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();

# Use content scripts carefully(谨慎使用内容脚本)

虽然内容脚本生活在一个孤立的世界中,但它们也无法免受攻击:

  • 内容脚本是扩展程序中与网页直接交互的唯一部分。因此,恶意网页可能会操纵内容脚本所依赖的 DOM 部分,或利用令人惊讶的 Web 标准行为,例如命名项目(named items)。
  • 为了与网页的 DOM 交互,内容脚本需要在与网页相同的渲染器进程中执行。这使得内容脚本容易通过旁道攻击(例如,Spectre)泄漏数据,并且如果恶意网页危及渲染器进程,则容易被攻击者接管。

敏感工作应在专用进程中执行,例如扩展程序的后台脚本(background script)。避免意外将扩展权限暴露给内容脚本:

  • 假设来自内容脚本的消息可能是由攻击者制作的(例如,验证和清理所有输入并保护您的脚本免受跨站点脚本攻击
  • 假设发送到内容脚本的任何数据都可能泄漏到网页。不要将敏感数据(例如来自扩展程序的秘密、来自其他网络来源的数据、浏览历史记录)发送到内容脚本。
  • 限制内容脚本可以触发的特权操作的范围。不允许内容脚本触发对任意 URL 的请求或将任意参数传递给扩展 API(例如,不允许将任意 URL 传递给 fetchchrome.tabs.create API)。

# Register and sanitize inputs(注册和清理输入)

通过将侦听器限制在扩展程序预期的范围内、验证传入数据的发送者并清理所有输入,来保护扩展程序免受恶意脚本的攻击。

如果扩展需要来自外部网站或扩展的通信,它应该只注册 runtime.onRequestExternal。始终验证发件人是否与可信来源相匹配。

// 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.");
});

通过清理用户输入和传入数据,甚至来自扩展本身和批准的来源,防止扩展执行攻击者的脚本。避免可执行的 API

function sanitizeInput(input) {
    return input.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}

By.一粒技术服务

results matching ""

    No results matching ""