Ursprungsübergreifende XMLHttpRequest-Anfrage

Reguläre Webseiten können das XMLHttpRequest-Objekt verwenden, um Daten von Remote- Server, aber sie sind durch die gleiche Ursprungsrichtlinie eingeschränkt. Content-Skripts initiieren Anfragen im Namen des Webursprungs, in den das Inhaltsskript eingeschleust wurde, Skripts unterliegen außerdem der Richtlinie für denselben Ursprung. (Content-Skripte unterliegen den CORB- seit Chrome 73 und CORS seit Chrome 83 Die Ursprünge der Erweiterung sind nicht so begrenzt: Ein Skript kann die Ausführung auf der Hintergrundseite oder im Vordergrund-Tab einer Erweiterung mit Remote-Servern kommunizieren, deren Ursprung ermittelt wird, sofern die Erweiterung ursprungsübergreifende Berechtigungen anfordert.

Ursprung der Erweiterung

Jede ausgeführte Erweiterung befindet sich in ihrem eigenen Sicherheitsherkunft. Ohne zusätzliche Anforderung Berechtigungen hat, kann die Erweiterung in der Installation Ressourcen mithilfe von XMLHttpRequest abrufen. Für Beispiel: Eine Erweiterung enthält eine JSON-Konfigurationsdatei namens config.json in einer config_resources enthält, kann die Erweiterung den Inhalt der Datei so abrufen:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();

Wenn die Erweiterung versucht, eine andere Sicherheitsquelle als sich selbst zu verwenden, z. B. https://www.google.com, Der Browser lässt dies nur zu, wenn die Erweiterung das entsprechende ursprungsübergreifende Berechtigungen.

Ursprungsübergreifende Berechtigungen anfordern

Durch Hinzufügen von Hosts oder Host-Übereinstimmungsmustern (oder beidem) im Abschnitt Berechtigungen der Seite manifest, kann die Erweiterung Zugriff auf Remote-Server außerhalb ihres Ursprungs anfordern.

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

Ursprungsübergreifende Berechtigungswerte können z. B. vollständig qualifizierte Hostnamen sein:

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

Es kann sich auch um Übereinstimmungsmuster wie die folgenden handeln:

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

Übereinstimmungsmuster: „https://*/“ ermöglicht HTTPS-Zugriff auf alle erreichbaren Domains. Hier muss die Übereinstimmung ähneln Content-Skript-Übereinstimmungsmustern, aber alle Pfadinformationen, die auf Host ignoriert.

Beachten Sie auch, dass der Zugriff sowohl durch den Host als auch durch das Schema gewährt wird. Wenn eine Erweiterung sowohl sichere als auch nicht sicheren HTTP-Zugriff auf einen bestimmten Host oder eine Gruppe von Hosts hat, müssen die Berechtigungen separat deklariert werden:

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

Sicherheitsaspekte

Cross-Site-Scripting-Sicherheitslücken vermeiden

Wenn Sie Ressourcen verwenden, die über XMLHttpRequest abgerufen wurden, sollten Sie auf Ihrer Hintergrundseite darauf achten, zum Opfer von Cross-Site-Scripting werden. Vermeiden Sie insbesondere die Verwendung gefährlicher APIs wie der unten:

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

Stattdessen sollten Sie sicherere APIs bevorzugen, die keine Skripts ausführen:

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

Content-Script-Zugriff auf ursprungsübergreifende Anfragen beschränken

Wenn Sie ursprungsübergreifende Anfragen im Namen eines Inhaltsskripts durchführen, sollten Sie sich vor Schädliche Webseiten, die versuchen, die Identität eines Content-Skripts zu stehlen Insbesondere ist es untersagt, um eine beliebige URL anzufordern.

Ein Beispiel: Eine Erweiterung führt eine ursprungsübergreifende Anfrage durch, um ein Content-Skript zuzulassen. den Preis eines Artikels ermitteln. Ein (unsicherer) Ansatz wäre, das Content-Skript anzugeben, Die genaue Ressource, die von der Hintergrundseite abgerufen werden soll.

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

Beim obigen Ansatz kann das Inhaltsskript die Erweiterung auffordern, jede URL abzurufen, die von der Erweiterung auf die das Unternehmen zugreifen kann. Eine bösartige Webseite kann möglicherweise solche Nachrichten fälschen und die Erweiterung durch Täuschung die Zugriff auf ursprungsübergreifende Ressourcen gewährt.

Entwerfen Sie stattdessen Nachrichten-Handler, die die Ressourcen beschränken, die abgerufen werden können. Darunter werden nur die itemId wird vom Content-Skript und nicht die vollständige URL bereitgestellt.

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 gegenüber HTTP bevorzugt

Seien Sie außerdem besonders vorsichtig bei Ressourcen, die über HTTP abgerufen werden. Wenn Ihre Erweiterung auf einem eines feindlichen Netzwerks könnte ein Netzwerkangreifer (auch als "man-in-the-middle" bezeichnet) die Antwort ändern. und greifen möglicherweise Ihre Erweiterung an. Stattdessen sollten Sie nach Möglichkeit HTTPS verwenden.

Content Security Policy anpassen

Wenn Sie die standardmäßige Content Security Policy für Apps oder Erweiterungen durch Hinzufügen eines content_security_policy nicht hinzugefügt haben, müssen Sie sicherstellen, dass alle Hosts, die Sie verbinden möchten. Die Standardrichtlinie schränkt Verbindungen zu Hosts zwar nicht ein, sei vorsichtig, wenn du explizit die Anweisungen connect-src oder default-src hinzufügst.