Freigeben über


Verwenden der Inhaltssicherheitsrichtlinie (Content Security Policy, CSP), um zu steuern, welche Ressourcen ausgeführt werden können

Um zu steuern, welche Inhalte von der Erweiterung ausgeführt werden können, verwenden Sie in der Datei der Erweiterung manifest.json den Schlüssel und den content_security_policy zugehörigen Richtlinienzeichenfolgenwert gemäß der folgenden Syntax:

{
    ...,
    "content_security_policy": "[policy string]"
    ...
}

Im Folgenden finden Sie z. B. die Standardrichtlinie für die Inhaltssicherheit, wie unten unter Einschränkungen für Standardrichtlinien beschrieben:

{
    ...,
    "content_security_policy": "script-src 'self'; object-src 'self'; worker-src 'self'"
    ...
}

Um eine große Anzahl von potenziellen problemen mit standortübergreifenden Skripts zu beheben, enthält das Microsoft Edge-Erweiterungssystem die Inhaltssicherheitsrichtlinie (Content Security Policy, CSP). CSP führt einige strenge Richtlinien ein, die Erweiterungen standardmäßig sicherer machen, und bietet Ihnen die Möglichkeit, Regeln für die Inhaltstypen zu erstellen und zu erzwingen, die von Ihren Erweiterungen und Anwendungen geladen und ausgeführt werden können.

Im Allgemeinen funktioniert CSP als Block-/Positivlistenmechanismus für Ressourcen, die von Ihrer Erweiterung geladen oder ausgeführt werden. Wenn Sie eine angemessene Richtlinie für Ihre Erweiterung definieren, können Sie die Ressourcen, die Ihre Erweiterung benötigt, sorgfältig prüfen und den Browser bitten, sicherzustellen, dass dies die einzigen Ressourcen sind, auf die Ihre Erweiterung Zugriff hat. Die Richtlinien bieten Sicherheit über die Hostberechtigungen, die Ihre Erweiterung anfordert. Sie stellen eine zusätzliche Schutzebene dar, keine Ersatzebene.

Im Gegensatz dazu wird eine solche Richtlinie auf einer Webseite über einen HTTP-Header oder über ein meta -Element definiert. Innerhalb des Microsoft Edge-Erweiterungssystems ist ein HTTP-Header oder ein meta -Element jedoch kein geeigneter Mechanismus.

Siehe:

Standardrichtlinieneinschränkungen

Pakete, die keine definieren manifest_version , verfügen nicht über eine Standardmäßige Inhaltssicherheitsrichtlinie.

Pakete, die verwenden manifest_version , weisen die folgende Standardrichtlinie für die Inhaltssicherheit auf:

script-src 'self'; object-src 'self'; worker-src 'self'

Die Richtlinie erhöht die Sicherheit, indem sie Erweiterungen und Anwendungen auf drei Arten einschränkt:

Code wie der folgende funktioniert nicht:

alert(eval("foo.bar.baz"));
window.setTimeout("alert('hi')", 10);
window.setInterval("alert('hi')", 10);
new Function("return foo.bar.baz");

Das Auswerten von JavaScript-Zeichenfolgen wie dieser ist ein gängiger XSS-Angriffsvektor. Stattdessen sollten Sie Code wie folgt schreiben:

alert(foo && foo.bar && foo.bar.baz);
window.setTimeout(function() { alert('hi'); }, 10);
window.setInterval(function() { alert('hi'); }, 10);
function() { return foo && foo.bar && foo.bar.baz };

Inline-JavaScript wird nicht ausgeführt

Inline-JavaScript wird nicht ausgeführt. Diese Einschränkung verbietet sowohl Inlineblöcke <script> als auch Inlineereignishandler, z <button onclick="...">. B. .

Die erste Einschränkung löscht eine große Klasse von cross-site scripting-Angriffen, da sie es unmöglich macht, das von einem böswilligen Drittanbieter bereitgestellte Skript versehentlich auszuführen. Es erfordert jedoch, dass Sie Ihren Code mit einer sauber Trennung zwischen Inhalt und Verhalten schreiben. Ein Beispiel könnte dies deutlicher machen. Sie können versuchen, ein Browseraktionsfenster als einzelnes pop-up.html Popup zu schreiben, das Folgendes enthält:

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script>
            function awesome() {
                // do something awesome!
            }

            function totallyAwesome() {
                // do something TOTALLY awesome!
            }

            function clickHandler(element) {
                setTimeout("awesome(); totallyAwesome()", 1000);
            }

            function main() {
                // Initialization work goes here.
            }
        </script>
    </head>
    <body onload="main();">
        <button onclick="clickHandler(this)">
            Click for awesomeness!
        </button>
    </body>
</html>

Aber drei Dinge müssen sich ändern, damit dies so funktioniert, wie Sie es erwarten:

  • Die clickHandler Definition muss in eine externe JavaScript-Datei verschoben werden (popup.js kann ein gutes Ziel sein).

  • Die Inline-Ereignishandlerdefinitionen müssen in Bezug auf addEventListener neu geschrieben und in popup.jsextrahiert werden. Wenn Sie Ihr Programm derzeit mit Code wie <body onload="main();">starten, sollten Sie es ersetzen, indem Sie es je nach Ihren Anforderungen mit dem DOMContentLoaded Ereignis des Dokuments oder dem load Ereignis des Fensters verbinden. Verwenden Sie ersteres, da sie in der Regel schneller ausgelöst wird.

  • Der setTimeout Aufruf muss umgeschrieben werden, um zu vermeiden, dass die Zeichenfolge "awesome(); totallyAwesome()" zum Ausführen in JavaScript konvertiert wird.

Diese Änderungen könnten in etwa wie folgt aussehen:

function awesome() {
    // Do something awesome!
}

function totallyAwesome() {
    // do something TOTALLY awesome!
}

function awesomeTask() {
    awesome();
    totallyAwesome();
}

function clickHandler(e) {
    setTimeout(awesomeTask, 1000);
}

function main() {
    // Initialization work goes here.
}

// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
    document.querySelector('button').addEventListener('click', clickHandler);
    main();
});
<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="popup.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Es werden nur lokale Skript- und Objektressourcen geladen.

Skript- und Objektressourcen können nur aus dem Erweiterungspaket und nicht aus dem Web geladen werden. Dadurch wird sichergestellt, dass Ihre Erweiterung nur den Code ausführt, den Sie speziell genehmigt haben, und verhindert, dass ein aktiver Netzwerk-Angreifer Ihre Anforderung für eine Ressource böswillig umleitet.

Anstatt Code zu schreiben, der vom Laden von jQuery (oder einer anderen Bibliothek) aus einem externen CDN abhängt, sollten Sie die spezifische Version von jQuery in Ihr Erweiterungspaket einschließen. Das heißt, anstelle von:

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Verwenden Sie stattdessen den folgenden Ansatz. Laden Sie die Datei herunter, fügen Sie sie in Ihr Paket ein, und schreiben Sie Folgendes:

<!doctype html>
<html>
    <head>
        <title>My Awesome Pop-up!</title>
        <script src="jquery.min.js"></script>
    </head>
    <body>
        <button>Click for awesomeness!</button>
    </body>
</html>

Lockerung der Standardrichtlinie

Sie können die Ausführung der folgenden Skripttypen zulassen:

Details finden Sie unten.

Inlineskript

Inlineskripts können zulässig sein, indem der Base64-codierte Hash des Quellcodes in der Richtlinie angegeben wird. Diesem Hash muss der verwendete Hashalgorithmus (sha256, sha384 oder sha512) vorangestellt werden. Ein Beispiel finden Sie unter W3C-Hashverwendung > für <Skriptelemente>.

Remoteskript

Wenn Sie externe JavaScript- oder Objektressourcen benötigen, können Sie die Richtlinie in begrenztem Umfang lockern, indem Sie sichere Ursprünge zulassen, von denen Skripts akzeptiert werden sollen. Stellen Sie sicher, dass Laufzeitressourcen, die mit erhöhten Berechtigungen einer Erweiterung geladen werden, genau die von Ihnen erwarteten Ressourcen sind und nicht durch einen aktiven Netzwerkangriff ersetzt werden. Da Man-in-the-Middle-Angriffe sowohl trivial als auch nicht erkennbar über HTTP sind, werden diese Ursprünge nicht akzeptiert.

Derzeit können Sie Ursprünge zulassen, die über die folgenden Schemas verfügen: blob, filesystem, httpsund extension. Der Hostteil des Ursprungs muss explizit für die https Schemas und extension angegeben werden. Generische Platzhalter wie https:, https://* und https://*.com sind nicht zulässig. Unterdomänenplatzhalter wie https://*.example.com sind zulässig. Domänen in der Liste Öffentliche Suffixe werden auch als generische Domänen der obersten Ebene betrachtet. Um eine Ressource aus diesen Domänen zu laden, muss die Unterdomäne explizit aufgeführt werden. Beispielsweise https://*.cloudfront.net ist ungültig, aber https://XXXX.cloudfront.net und https://*.XXXX.cloudfront.net kann sein allowlisted.

Zur Vereinfachung der Entwicklung können Ressourcen, die über HTTP von Servern auf Ihrem lokalen Computer geladen werden, sein allowlisted. Sie können Skript- und Objektquellen auf jeder Port von http://127.0.0.1 oder http://localhostzulassen.

Hinweis

Die Einschränkung für Ressourcen, die über HTTP geladen werden, gilt nur für die Ressourcen, die direkt ausgeführt werden. Sie können z. B. weiterhin Verbindungen mit jedem beliebigen Ursprung herstellen XMLHTTPRequest . Die Standardrichtlinie schränkt oder eine der anderen CSP-Direktiven in keiner Weise ein connect-src .

Eine gelockerte Richtliniendefinition, die das Laden von Skriptressourcen über example.com HTTPS ermöglicht, kann wie folgt aussehen:

"content_security_policy": "script-src 'self' https://example.com; object-src 'self'"

Hinweis

Sowohl als object-src auch script-src werden durch die Richtlinie definiert. Microsoft Edge akzeptiert keine Richtlinie, die nicht jeden dieser Werte auf (mindestens) "self" beschränkt.

Ausgewertetes JavaScript

Die Richtlinie für eval() und verwandte Funktionen wie setTimeout(String), setInterval(String)und new Function(String) kann durch Hinzufügen unsafe-eval zu Ihrer Richtlinie gelockert werden:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Sie sollten jedoch lockere Richtlinien vermeiden. Diese Arten von Funktionen sind berüchtigte XSS-Angriffsvektoren.

Straffen der Standardrichtlinie

Sie können diese Richtlinie in jedem Umfang verschärfen, den Ihre Erweiterung zulässt, um die Sicherheit auf Kosten der Bequemlichkeit zu erhöhen. Wenn Sie angeben möchten, dass Ihre Erweiterung nur Ressourcen eines beliebigen Typs (Images usw.) aus dem zugeordneten Erweiterungspaket laden kann, kann z. B. eine Richtlinie von default-src 'self' geeignet sein.

Inhaltsskripts

Die zu behandelnde Richtlinie gilt für die Hintergrund- und Ereignisseiten der Erweiterung. Die Anwendung der Inhaltsskripts auf die Inhaltsskripts der Erweiterung ist komplizierter.

Inhaltsskripts unterliegen im Allgemeinen nicht dem CSP der Erweiterung. Da Inhaltsskripts kein HTML-Code sind, besteht die Standard Auswirkung davon darin, dass sie auch dann verwenden eval können, wenn der CSP der Erweiterung nicht angibtunsafe-eval, obwohl dies nicht empfohlen wird. Darüber hinaus gilt der CSP der Seite nicht für Inhaltsskripts. Komplizierter sind <script> Tags, die Inhaltsskripts erstellen und in das DOM der Seite einfügen, auf der sie ausgeführt werden. Auf diese werden in Zukunft als dominjizierte Skripts verwiesen.

Dom hat Skripts eingefügt, die sofort nach der Einschleusung in die Seite ausgeführt werden, wie Sie es erwarten würden. Stellen Sie sich ein Inhaltsskript mit folgendem Code als einfaches Beispiel vor:

document.write("<script>alert(1);</script>");

Dieses Inhaltsskript löst direkt auf der aus alertdocument.write(). Beachten Sie, dass dies unabhängig von der Richtlinie ausgeführt wird, die eine Seite angibt. Das Verhalten wird jedoch komplizierter, sowohl innerhalb des mit DOM eingefügten Skripts als auch für alle Skripts, die nicht sofort nach der Einschleusung ausgeführt werden.

Angenommen, Ihre Erweiterung wird auf einer Seite ausgeführt, die einen zugeordneten CSP bereitstellt, der angibt script-src 'self'. Stellen Sie sich nun vor, das Inhaltsskript führt den folgenden Code aus:

document.write("<button onclick='alert(1);'>click me</button>'");

Wenn ein Benutzer auf diese Schaltfläche klickt, wird das onclick Skript nicht ausgeführt. Dies liegt daran, dass das Skript nicht sofort ausgeführt wurde und Code, der erst interpretiert wird, wenn das click Ereignis eintritt, nicht als Teil des Inhaltsskripts betrachtet wird, sodass der CSP der Seite (nicht der Erweiterung) das Verhalten einschränkt. Und da dieser CSP nicht angibt unsafe-inline, wird der Inlineereignishandler blockiert.

Die richtige Methode zum Implementieren des gewünschten Verhaltens in diesem Fall besteht darin, den onclick Handler wie folgt als Funktion aus dem Inhaltsskript hinzuzufügen:

document.write("<button id='mybutton'>click me</button>'");
var button = document.getElementById('mybutton');
button.onclick = function() {
      alert(1);
};

Ein weiteres ähnliches Problem tritt auf, wenn das Inhaltsskript Folgendes ausführt:

var script = document.createElement('script');
script.innerHTML = 'alert(1);'
document.getElementById('body').appendChild(script);

In diesem Fall wird das Skript ausgeführt, und die Warnung wird angezeigt. Beachten Sie jedoch diesen Fall:

var script = document.createElement('script');
script.innerHTML = 'eval("alert(1);")';
=document.getElementById('body').appendChild(script);

Während das anfängliche Skript ausgeführt wird, wird der Aufruf von eval blockiert. Das heißt, während die anfängliche Skriptlaufzeit zulässig ist, wird das Verhalten innerhalb des Skripts durch den CSP der Seite geregelt. Je nachdem, wie Sie dominjizierte Skripts in Ihrer Erweiterung schreiben, können Sich Änderungen am CSP der Seite also auf das Verhalten Ihrer Erweiterung auswirken.

Da Inhaltsskripts vom CSP der Seite nicht betroffen sind, ist dies ein guter Grund, so viel Verhalten wie möglich in das Inhaltsskript zu setzen, anstatt dominjizierte Skripts.

Siehe auch

Hinweis

Teile dieser Seite sind Änderungen, die auf Arbeiten basieren, die von Google erstellt und geteilt und gemäß den in der Creative Commons Attribution 4.0 International License beschriebenen Bedingungen verwendet werden. Die ursprüngliche Seite finden Sie hier.

Creative Commons License Dieses Werk ist unter einer Creative Commons Attribution 4.0 International License lizenziert.