クロスオリジンの XMLHttpRequest

通常のウェブページでは、XMLHttpRequest オブジェクトを使用してリモート ただし、同一オリジン ポリシーによって制限されます。コンテンツ スクリプトがリクエストを開始する コンテンツ スクリプトが挿入されたウェブオリジンに代わってコンテンツが挿入され、 スクリプトにも同一オリジン ポリシーが適用されます。(コンテンツのスクリプトは CORB の対象となっている) Chrome 73 以降、CORS は Chrome 83 以降)。拡張機能のオリジンはそれほど制限されていない - スクリプト 拡張機能のバックグラウンド ページまたはフォアグラウンド タブで実行中のアプリは、外部 IP アドレスを持つリモート サーバーと通信できます。 拡張機能がクロスオリジン権限をリクエストしている限り、そのオリジン

拡張機能のオリジン

実行中の各拡張機能は、それぞれ個別のセキュリティ オリジン内に存在します。追加のリクエストなし 権限があれば、拡張機能は 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 など)を使用しようとすると、 拡張機能が適切なクロスオリジンをリクエストしない限り、ブラウザはこれを許可しない 付与できます。

クロスオリジン権限のリクエスト

プロジェクトの権限セクションに、 manifest ファイルを指定することで、拡張機能は配信元外のリモート サーバーへのアクセスをリクエストできます。

{
  "name": "My extension",
  ...
  "permissions": [
    "https://www.google.com/"
  ],
  ...
}

クロスオリジン権限の値は、次のように完全修飾ホスト名にすることができます。

  • "https://www.google.com/"
  • "https://www.gmail.com/"

または、次のような一致パターンを使用することもできます。

  • "https://*.google.com/"
  • "https://*/"

一致パターン: 「https://*/」到達可能なすべてのドメインへの HTTPS アクセスを許可します。なお、ここでは tf.data.Dataset コンテンツ スクリプトの一致パターンと似ていますが、 無視されます。

また、アクセス権はホストとスキームの両方で付与されることに注意してください。拡張機能が 特定のホストまたはホストセットに非セキュア HTTP アクセスを行う場合、権限を個別に宣言する必要があります。

"permissions": [
  "http://www.google.com/",
  "https://www.google.com/"
]

セキュリティ上の考慮事項

クロスサイト スクリプティングの脆弱性の回避

XMLHttpRequest を介して取得したリソースを使用する場合、バックグラウンド ページでは、 クロスサイト スクリプティングの被害を受ける可能性があります。具体的には、Terraform のような危険な 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();

コンテンツ スクリプトによるクロスオリジン リクエストへのアクセスを制限する

コンテンツ スクリプトの代理としてクロスオリジン リクエストを実行する場合は、 悪意のあるウェブページが該当し、コンテンツ スクリプトになりすまします。特に、kubectl の 任意の URL をリクエストします。

拡張機能がクロスオリジン リクエストを実行して、コンテンツ スクリプトに 商品の価格を知るため(安全性が低い)方法の一つとして、コンテンツ スクリプトで バックグラウンド ページで取得される正確なリソース。

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

上記のアプローチでは、コンテンツ スクリプトは、拡張機能が取得する URL を取得するよう拡張機能に指示できます。 できます。悪意のあるウェブページが、このようなメッセージを偽造して拡張機能をだまし、 クロスオリジン リソースへのアクセス権を付与します。

代わりに、取得できるリソースを制限するメッセージ ハンドラを設計します。以下は、 itemId はコンテンツ スクリプトによって提供されるものであり、完全な URL ではありません。

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 => ...);

HTTP より HTTPS を優先する

また、HTTP 経由で取得されるリソースには特に注意してください。拡張機能が ネットワーク攻撃者(別名「中間者」"man-in-the-middle")によってレスポンスが 拡張機能を攻撃する可能性があります可能な限り HTTPS を優先してください。

コンテンツ セキュリティ ポリシーの調整

追加することにより、アプリや拡張機能のデフォルトのコンテンツ セキュリティ ポリシーを変更する場合は、 content_security_policy 属性をマニフェストに追加すると、その接続先のすべてのホストを 許可することを確認します。デフォルトのポリシーではホストへの接続は制限されませんが、 connect-src ディレクティブまたは default-src ディレクティブを明示的に追加する場合は注意が必要です。