セキュリティの確保

拡張機能はブラウザ内の特別な権限にアクセスできるため、攻撃者にとって魅力的なターゲットとなります。拡張機能が侵害されると、その拡張機能のすべてのユーザーが、悪意のある侵入や不要な侵入に対して脆弱になります。 以下の方法で拡張機能のセキュリティを確保し、ユーザーを保護してください。

デベロッパー アカウントを保護する

拡張機能のコードは Google アカウントを通じてアップロードおよび更新されます。デベロッパーのアカウントが侵害されると、攻撃者は悪意のあるコードをすべてのユーザーに直接プッシュする可能性があります。2 要素認証(可能であればセキュリティ キーを使用)を有効にして、これらのアカウントを保護してください。

適切なメンバーのロールを使用する

パブリッシャーに複数のメンバーがいる場合は、各 ユーザーに付与されるロールが適切であることを確認してください。

HTTP を使用しない

データをリクエストまたは送信する場合は、HTTP 接続を避けてください。HTTP 接続には盗聴者がいるか、変更が含まれていると想定してください。HTTPS にはセキュリティ機能が組み込まれており、ほとんどの中間者攻撃を回避できるため、常に 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_accessible_resources" の下で、 拡張機能がウェブサイトや攻撃者によって検出されるようになります。

{
  ...
  "web_accessible_resources": [
    {
      "resources": [ "test1.png", "test2.png" ],
      "matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
    }
  ]
  ...
}

ウェブからアクセス可能なリソースが多いほど、潜在的な攻撃者が悪用できる経路が増えます。これらのファイルは最小限にしてください。

明示的なコンテンツ セキュリティ ポリシーを含める

クロスサイト スクリプティング攻撃を防ぐため、マニフェストに拡張機能のコンテンツ セキュリティ ポリシーを含めます。拡張機能がリソースを自身からのみ読み込む場合は、次のように登録します。

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
   "content_security_policy": {
    "extension_pages": "default-src 'self'"
  },
  "manifest_version": 3
}

拡張機能でウェブ アセンブリを使用する必要がある場合や、サンドボックス化されたページの制限を強化する必要がある場合は、次のように追加できます。

{
  "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 の一部を操作したり、 名前付きアイテムなど、ウェブ標準の予期しない動作を悪用したりする可能性があります。
  • ウェブページの DOM とやり取りするには、コンテンツ スクリプトをウェブページと同じレンダラ プロセスで実行する必要があります。これにより、コンテンツ スクリプトはサイドチャネル攻撃 (Spectreなど)によるデータ漏洩に対して脆弱になり、悪意のあるウェブページがレンダラ プロセスを侵害した場合 、攻撃者に不正使用される可能性があります。

機密データ(ユーザーの個人情報など)や、ブラウザの機能にアクセスできる Chrome API を使用するオペレーションは、拡張機能の Service Worker で実行する必要があります。拡張機能の権限がコンテンツ スクリプトに誤って公開されないようにしてください。

  • コンテンツ スクリプトからのメッセージは攻撃者によって作成された可能性があると想定してください(例: すべての入力を検証してサニタイズし、スクリプトをクロスサイト スクリプティングから保護するなど)。
  • コンテンツ スクリプトに送信されたデータがウェブページに漏洩する可能性があると想定してください。センシティブ データ(拡張機能の Secret、他のウェブにおけるオリジンからのデータ、閲覧履歴など)をコンテンツ スクリプトに送信しないでください。
  • コンテンツ スクリプトによってトリガーできる権限付きアクションのスコープを制限します。コンテンツ スクリプトが任意の URL へのリクエストをトリガーしたり、任意の引数を拡張機能 API に渡したりすることを許可しないでください(たとえば、任意の URL を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.");
});