Das Erweiterungssystem von Chrome erzwingt eine relativ strikte standardmäßige Content Security Policy (CSP).
Die Richtlinieneinschränkungen sind einfach: Das Skript muss in separate
JavaScript-Dateien müssen Inline-Event-Handler zur Verwendung von addEventListener
konvertiert werden und eval()
ist
deaktiviert. Für Chrome-Apps gelten noch strengere Richtlinien. Wir sind mit den Sicherheitseigenschaften dieser Richtlinien sehr zufrieden.
Wir wissen jedoch, dass eine Vielzahl von Bibliotheken eval()
- und eval
-ähnliche Konstrukte verwendet, z. B.:
new Function()
für die Leistungsoptimierung und einen einfachen Ausdruck. Vorlagenbibliotheken sind
besonders anfällig für diese Art der Implementierung. Einige, z. B. Angular.js, unterstützen CSP auswärts.
viele gängige Frameworks noch nicht auf einen Mechanismus aktualisiert, der mit
Erweiterungen Welt mit weniger als eval
. Die Einstellung der Unterstützung dieser Funktion hat sich daher für Entwickler als problematischer als erwartet erwiesen.
In diesem Dokument wird Sandboxing als sicherer Mechanismus vorgestellt, mit dem Sie diese Bibliotheken in Ihre Projekte einbinden können, ohne die Sicherheit zu gefährden. Der Begriff Erweiterungen wird im Folgenden aus Gründen der Übersichtlichkeit verwendet. Das Konzept gilt aber auch für Anwendungen.
Warum Sandbox?
eval
ist innerhalb einer Erweiterung gefährlich, da der von ihm ausgeführte Code Zugriff auf alles im
Erweiterung mit umfangreichen Berechtigungen. Es stehen zahlreiche leistungsstarke chrome.*
APIs zur Verfügung, die
die Sicherheit und den Datenschutz eines Nutzers erheblich beeinträchtigen; Eine einfache Daten-Exfiltration ist für uns am wenigsten sorgen.
Die angebotene Lösung ist eine Sandbox, in der eval
Code ausführen kann, ohne auf den
die Daten der Erweiterung
oder die hochwertigen APIs der Erweiterung. Keine Daten, keine APIs, kein Problem.
Dazu werden bestimmte HTML-Dateien im Erweiterungspaket als Sandbox-Dateien aufgeführt.
Wenn eine Seite mit Sandbox geladen wird, wird sie an einen eindeutigen Ursprung verschoben und der Zugriff auf chrome.*
APIs wird ihr verweigert. Wenn wir diese Sandbox-Seite über eine iframe
in unsere Erweiterung laden, können wir ihr Nachrichten übergeben, sie auf diese Nachrichten reagieren lassen und darauf warten, dass sie uns ein Ergebnis zurückgibt. Dieser einfache Nachrichtenmechanismus gibt uns alles, was wir brauchen, um eval
-gesteuerte
im Workflow unserer Erweiterung.
Sandbox erstellen und verwenden
Wenn Sie direkt mit dem Code beginnen möchten, laden Sie die Beispielerweiterung für die Sandbox herunter und legen Sie los. Es handelt sich um ein funktionierendes Beispiel für eine kleine Messaging-API, die auf der Handlebars-Template-Bibliothek basiert. Sie sollten damit alles haben, was Sie für den Einstieg benötigen. Für diejenigen, die noch etwas mehr Erklärung benötigen, gehen wir das Beispiel hier gemeinsam durch.
Dateien im Manifest auflisten
Jede Datei, die in einer Sandbox ausgeführt werden soll, muss im Manifest der Erweiterung aufgeführt sein. Dazu fügen Sie eine sandbox
-Eigenschaft hinzu. Dies ist ein wichtiger Schritt, der leicht vergessen wird. Überprüfen Sie daher,
die in der Sandbox ausgeführte Datei im Manifest aufgeführt ist. In diesem Beispiel wird die Datei „sandbox.html“ in einer Sandbox ausgeführt. Der Manifesteintrag sieht so aus:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
Datei aus der Sandbox laden
Damit wir etwas Interessantes mit der Datei in der Sandbox tun können, müssen wir sie in einem Kontext laden, in dem sie vom Code der Erweiterung angesprochen werden kann. Hier wurde sandbox.html über eine iframe
in die Ereignisseite (eventpage.html) der Erweiterung geladen. eventpage.js enthält Code, der jedes Mal, wenn auf die Browseraktion geklickt wird, eine Nachricht an die Sandbox sendet. Dazu wird die iframe
auf der Seite gefunden und die postMessage
-Methode auf ihrer contentWindow
ausgeführt. Die Nachricht ist ein Objekt
mit zwei Eigenschaften: context
und command
. Wir gehen gleich auf beide ein.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
API finden Sie in der postMessage
-Dokumentation auf MDN. Es ist ziemlich vollständig und lohnt sich zu lesen. Beachten Sie insbesondere, dass Daten nur dann hin- und hergeleitet werden können, wenn sie serialisierbar sind. Funktionen sind das beispielsweise nicht.Etwas Gefährliches tun
Wenn sandbox.html
geladen wird, wird die Handlebars-Bibliothek geladen und eine Inline erstellt und kompiliert.
wie in Handlebars vorschlägt:
<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
<div class="entry">
<h1>Hello, !</h1>
</div>
</script>
<script>
var templates = [];
var source = document.getElementById('hello-world-template').innerHTML;
templates['hello'] = Handlebars.compile(source);
</script>
Das scheitert nicht! Handlebars.compile
verwendet zwar letztendlich new Function
, aber es funktioniert
und wir haben eine kompilierte Vorlage in templates['hello']
.
Ergebnis zurückgeben
Wir stellen diese Vorlage zur Verwendung zur Verfügung, indem wir einen Nachrichten-Listener einrichten, der Befehle akzeptiert
aus der Ereignisseite aus. Anhand der übergebenen command
wird bestimmt, was getan werden soll. Sie könnten sich vorstellen, mehr als nur zu rendern, z. B. Vorlagen zu erstellen. Vielleicht verwalten Sie sie in einigen
und die context
wird zum Rendern direkt an die Vorlage übergeben. Der gerenderte HTML-Code
an die Ereignisseite zurück, damit die Erweiterung später sinnvolle Aktionen durchführen kann:
<script>
window.addEventListener('message', function(event) {
var command = event.data.command;
var name = event.data.name || 'hello';
switch(command) {
case 'render':
event.source.postMessage({
name: name,
html: templates[name](event.data.context)
}, event.origin);
break;
// case 'somethingElse':
// ...
}
});
</script>
Auf der Veranstaltungsseite erhalten wir diese Nachricht und verwenden html
etwas Interessantes.
die uns übergeben wurden. In diesem Fall geben wir es einfach über eine Desktopbenachrichtigung aus. Es ist aber durchaus möglich, diesen HTML-Code sicher als Teil der Benutzeroberfläche der Erweiterung zu verwenden. Einfügen über
innerHTML
stellt kein erhebliches Sicherheitsrisiko dar, da selbst ein vollständiger Kompromittierung der Sandbox
durch einige clevere Angriffe keine gefährlichen Skript- oder Plug-in-Inhalte
den Kontext der Erweiterung mit
hohen Berechtigungen.
Dieser Mechanismus vereinfacht die Erstellung von Vorlagen, ist aber natürlich nicht darauf beschränkt. Jeder Code, der unter einer strengen Content Security Policy nicht standardmäßig funktioniert, kann in einer Sandbox ausgeführt werden. Tatsächlich ist es oft sinnvoll, Komponenten Ihrer Erweiterungen, die richtig ausgeführt werden würden, in einer Sandbox zu platzieren, um jedes Teil Ihres Programms auf die kleinste Anzahl von Berechtigungen zu beschränken, die für die ordnungsgemäße Ausführung erforderlich sind. Google-Präsentation Write Secure Web Apps and Chrome Extensions Bei der I/O 2012 finden Sie einige gute Beispiele für diese Techniken in der Praxis. .