„eval“ in Chrome-Erweiterungen verwenden

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. Chrome-Apps haben noch strengere Richtlinien und wir sind mit der Sicherheit sehr zufrieden Eigenschaften dieser Richtlinien.

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, wie 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. Es hat sich daher als besser erwiesen, dass diese Funktion nicht mehr unterstützt wird. problematisch als erwartet.

In diesem Dokument wird die sichere Sandbox-Technologie vorgestellt, mit der Sie diese Bibliotheken in Ihre Projekte einbinden können. ohne Abstriche bei der Sicherheit machen zu müssen. Der Einfachheit halber verwenden wir durchgehend Erweiterungen, aber gilt das Konzept gleichermaßen 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.

Dies erreichen wir, indem wir bestimmte HTML-Dateien im Erweiterungspaket als Sandbox-Technologie auflisten. Wenn eine in einer Sandbox ausgeführte Seite geladen wird, wird sie an einen eindeutigen Ursprung verschoben und abgelehnt. Zugriff auf chrome.* APIs Wenn wir diese in einer Sandbox ausgeführte Seite über iframe in unsere Erweiterung laden, kann es die Nachrichten weiterleiten, es auf diese Nachrichten reagieren und darauf warten, dass es uns ein Ergebnis. Dieser einfache Nachrichtenmechanismus gibt uns alles, was wir brauchen, um eval-gesteuerte im Workflow unserer Erweiterung.

Sandbox erstellen und verwenden

Wenn Sie direkt in den Code einsteigen möchten, holen Sie sich die Sandboxing-Beispielerweiterung deaktiviert. Es ist ein funktionierendes Beispiel für eine winzige Messaging-API, die auf dem Handlebars basiert. Vorlagenbibliothek, die Ihnen alles bietet, was Sie für den Einstieg brauchen. Für diejenigen unter Ihnen, die Erklären, sehen wir uns das Beispiel hier gemeinsam an.

Dateien im Manifest auflisten

Jede Datei, die in einer Sandbox ausgeführt werden soll, muss im Erweiterungsmanifest durch Hinzufügen eines sandbox-Property. 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 geschickt in einer Sandbox ausgeführt. namens "sandbox.html". Der Manifesteintrag sieht so aus:

{
  ...,
  "sandbox": {
     "pages": ["sandbox.html"]
  },
  ...
}

In der Sandbox ausgeführte Datei laden

Um mit der in der Sandbox ausgeführten Datei etwas Interessantes zu tun, müssen wir sie in einem Kontext laden, in dem kann der Code der Erweiterung berücksichtigt werden. Hier wurde sandbox.html in den Ereignisseite (eventpage.html) der Erweiterung über iframe. eventpage.js enthält Code. , die jedes Mal, wenn auf die Browseraktion geklickt wird, eine Nachricht an die Sandbox sendet, indem das iframe-Objekt gesucht wird. auf der Seite und führen die postMessage-Methode auf der entsprechenden contentWindow aus. Die Nachricht ist ein Objekt mit zwei Eigenschaften: context und command. Wir sehen uns beides gleich an.

chrome.browserAction.onClicked.addListener(function() {
 var iframe = document.getElementById('theFrame');
 var message = {
   command: 'render',
   context: {thing: 'world'}
 };
 iframe.contentWindow.postMessage(message, '*');
});
Allgemeine Informationen zur postMessage API findest du in der postMessage-Dokumentation auf MDN . Sie ist ziemlich vollständig und lesenswert. Beachten Sie insbesondere, dass Daten nur dann hin- und hergeleitet werden können, wenn sie serialisierbar sind. Funktionen hingegen 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 bestimmen wir, was zu tun ist. Sie können Stellen Sie sich vor, Sie würden mehr tun, als nur Rendering. vielleicht Vorlagen 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 sie in einer Desktop-Benachrichtigung wieder, aber kann dieser HTML-Code sicher als Teil der Benutzeroberfläche der Erweiterung verwendet werden. 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 erleichtert das Erstellen von Vorlagen, ist aber natürlich nicht auf Vorlagen beschränkt. Beliebig Code, der gemäß einer strengen Content Security Policy nicht sofort funktioniert, kann in einer Sandbox ausgeführt werden. in Es ist oft nützlich, die Komponenten der Erweiterungen in einer Sandbox auszuführen, die korrekt ausgeführt werden. jedes Teil Ihres Programms auf die kleinstmöglichen Berechtigungen zu beschränken, die erforderlich sind, ordnungsgemäß ausführen. Google-Präsentation Write Secure Web Apps and Chrome Extensions Auf der I/O 2012 finden Sie einige gute Beispiele für diese Techniken in der Praxis. .