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:
- Inhaltssicherheitsrichtlinie (Content Security Policy, CSP) bei MDN.
- Manifest: Inhaltssicherheitsrichtlinie in der Chrome-Erweiterungsreferenz>.
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:
Eval und verwandte Funktionen sind deaktiviert.
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 inpopup.js
extrahiert 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 demDOMContentLoaded
Ereignis des Dokuments oder demload
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
, https
und 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://localhost
zulassen.
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 alert
document.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
- Inhaltssicherheitsrichtlinie (Content Security Policy, CSP) bei MDN.
- Manifest: Inhaltssicherheitsrichtlinie in der Chrome-Erweiterungsreferenz>.
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.
Dieses Werk ist unter einer Creative Commons Attribution 4.0 International License lizenziert.