2012-08-31 7 views
27

Ich muss von Benutzern eingereichte Skripts auf meiner Website (etwa wie jsfiddle) dienen. Ich möchte, dass die Skripts auf den Browsern von Besuchern auf sichere Weise ausgeführt werden, isoliert von der Seite, auf der sie geschaltet werden. Da der Code von Benutzern übermittelt wird, kann nicht garantiert werden, dass er vertrauenswürdig ist.Wie kann ich nicht vertrauenswürdigen JavaScript-Inhalt, der von Benutzern eingegeben wurde, in Sandbox verschieben?

Im Moment kann ich von drei Möglichkeiten denken:

  • Diene dem Benutzer übermittelten Inhalte in einem iframe aus einer anderen Domäne, und verlassen sich auf die Same Origin Policy. Dies würde erfordern, eine zusätzliche Domäne einzurichten, die ich möglichst vermeiden möchte. Ich glaube, so macht es jsfiddle. Das Skript kann immer noch etwas Schaden anrichten, zum Beispiel top.location.href, was weniger als ideal ist. http://jsfiddle.net/PzkUw/
  • Verwenden Sie die sandbox attribute. Ich vermute, dass dies in den Browsern nicht gut unterstützt wird.
  • Sanitize die Skripte vor dem Servieren von ihnen. Ich würde lieber nicht dorthin gehen.

Gibt es andere Lösungen oder Empfehlungen zu den oben genannten?

aktualisieren

Wenn, wie ich vermute, die erste Option ist die beste Lösung, was kann ein schädliches Skript tun andere als die obere Fensterposition zu ändern, und wie kann ich das verhindern? Ich kann bestimmte Skripte basierend auf statischer Code-Analyse manipulieren oder ablehnen, aber dies ist hard gegeben die Anzahl der Möglichkeiten, auf die Objekte zugegriffen werden können und die Schwierigkeit, statisches Javaskript im Allgemeinen zu analysieren. Zumindest würde es einen vollwertigen Parser und eine Reihe von komplexen Regeln erfordern (einige, aber ich vermute nicht alle, die in JSLint vorhanden sind).

+2

Ich denke, Ihre Sub-Domain-Idee ist am besten. Ich habe diese Frage selbst untersucht und konnte keine bessere Lösung finden. Ich spielte einmal mit dem Laden der Skripte dynamisch über XmlHttpRequest und Ausführen von eval - ich weiß nicht, warum ich es fallen gelassen, obwohl. –

+0

In Verbindung stehend: http://stackoverflow.com/questions/958997/frame-buster-buster-buster-code-needed – Petah

+0

Ich stimme @JeremyJStarcher zu. Unabhängig davon, haben Sie die Möglichkeit, bestimmte JS-Elemente zu kontrollieren, wobei ** window ** am wichtigsten ist? Wenn ja, würde ich versuchen, bestimmte Anfragen aus dem iframe abzulehnen, aber ich bin mir nicht sicher, wie einfach das wäre. – inhan

Antwort

4

Einige Ideen von Tools, die in Ihrer Anwendung hilfreich sein könnten - sie greifen das Problem aus zwei verschiedenen Richtungen an: Caja kompiliert den nicht vertrauenswürdigen JavaScript-Code zu etwas, das sicher ist, während AdSafe eine Teilmenge von JavaScript definiert, die sicher zu verwenden ist.

Caja

Caja

Die Caja Compiler ist ein Werkzeug für Dritte HTML machen, CSS und JavaScript sicher in Ihre Website einbinden. Es ermöglicht eine umfassende Interaktion zwischen der eingebetteten Seite und den eingebetteten Anwendungen. Caja verwendet ein Objektsicherheitsmodell, um eine Vielzahl flexibler Sicherheitsrichtlinien zu ermöglichen, sodass Ihre Website effektiv steuern kann, was eingebetteter Code von Drittanbietern mit Benutzerdaten zu tun hat.

AdSafe

AdSafe

AdSafe macht es sicher Gast Code (wie Dritte scripted Werbung oder Widgets) auf einer Web-Seite zu setzen. ADSafe definiert eine Teilmenge von JavaScript, die leistungsstark genug ist, um Gast-Code zu ermöglichen, wertvolle Interaktionen durchzuführen, während gleichzeitig böswillige oder versehentliche Beschädigung oder Intrusion verhindert wird. Die ADSafe-Teilmenge kann mechanisch mit Tools wie JSLint verifiziert werden, so dass keine menschliche Prüfung erforderlich ist, um den Gastcode auf Sicherheit hin zu überprüfen.Die ADSafe-Untergruppe erzwingt auch gute Programmierpraktiken, wodurch die Wahrscheinlichkeit steigt, dass der Gastcode korrekt ausgeführt wird.

+0

Ich habe in AdSafe geschaut. Es ist für Skripte gedacht, die nicht in Frames sind und daher sehr restriktiv sind. Zum Beispiel können Sie nicht 'a [i] = 1' tun. Ich denke, dass die Beschränkungen die Mehrheit der legitimen Nutzer erschrecken können. Wirf einen Blick auf Caja. – Flash

+0

Sie können jedoch 'a [+ i] = 1 'tun.(Dies ist der Fall, wenn jemand 'a = Fenster schreibt; i = 'ev' + 'al'', dann würde' a [i] '' eval' bedeuten und es wäre unmöglich, diese Möglichkeit statisch zu eliminieren.) Aber Sie haben Recht dass es für Ihre Bedürfnisse zu restriktiv sein könnte. – rsp

26

Erstellen Sie eine gut definierte Nachrichtenschnittstelle, und verwenden Sie JavaScript Web Worker für den Code, den Sie sandboxieren möchten. HTML5 Web Workers

Web Workers haben keinen Zugriff auf die folgenden DOM-Objekte. Objekt

  • Das Fenster

  • Das Dokument-Objekt

  • Das übergeordnete Objekt

So können sie Ihre Seite nicht umleiten oder Daten über sie verändern.

Sie können eine Vorlage und eine gut definierte Messaging-Schnittstelle erstellen, so dass Benutzer Web Worker-Skripte erstellen können, aber Ihr Skript würde das letzte Wort darüber haben, was manipuliert wird.

EDIT Kommentar von Jordan Gray verstopft eine JavaScript-Bibliothek, die das zu tun scheint, was ich oben beschrieben habe. https://github.com/eligrey/jsandbox

+0

Klingt wie eine gute Alternative, könnte aber zu restriktiv sein. Trotzdem +1 für die Idee. – Christoph

+1

Guter Vorschlag. Meine Sorge ist, dass ältere Browser dies nicht unterstützen. Können Web-Worker auch keine AJAX-Anfragen stellen (was bedeutet, dass ich immer noch von einer anderen Domain aus liefern muss)? – Flash

+0

@Andrew - In welchem ​​Szenario sehen Sie einen Web-Mitarbeiter mit AJAX-Fähigkeiten als Problem? Wenn Sie sich Sorgen machen, dass das Worker-Skript den Benutzer in Ihrer eigenen Domäne darstellt, können Sie einfach cookie-lose Sitzungen verwenden und dieses Problem vermeiden. Was die Browser-Kompatibilität angeht, unterstützen yep, IE9 und darunter HTML5 nicht. –

-4

Wenn Sie einige Stück Code Sandbox, indem es Zugang ist das Fenster, zu sagen Dokument und Eltern Element Sie es erreichen könnte, indem es in einem Verschluss Einwickeln, wo diese lokalen leeren Variablen sind:

(function(window, document, parent /* Whatever you want to remove */){ 
    console.log(this);  // Empty object 
    console.log(window); // undefined 
    console.log(document); // undefined 
    console.log(parent); // undefined 
}).call({}); 

es mit einem leeren Objekt Aufruf ist wichtig, weil sonst diese zum Fenster Objekt zeigen wird

+7

'console.log (function() {return this;}());': P – Flash

2

Wie bereits erwähnt, das sandbox Attribut der iframe wird bereits von den wichtigsten Browsern unterstützt, aber ich würde zusätzlich eine gemischte Lösung vorschlagen: einen Web-Worker innerhalb der Sandbox Iframe zu starten. Das würde einen separaten Thread geben und das Sandbox-Iframe-DOM vor dem nicht vertrauenswürdigen Code schützen. So funktioniert meine Jailed Bibliothek. Darüber hinaus können Sie alle Einschränkungen umgehen, indem Sie beliebige Funktionen in die Sandbox exportieren.

+0

Frage zu Ihrer Bibliothek, warum führen Sie den Code in einem Sandkasten Iframe UND ein Web Worker? Wäre es nicht sicher genug, einen normalen Iframe zu haben, und dann den nicht vertrauenswürdigen Code in einem Web-Worker auszuführen? Der Web-Worker konnte nicht auf das dom des iframes zugreifen oder etwas anderes tun, außer was Sie in Ihren On-Message-Callbacks tun. Hab ich recht? – lastmjs

+2

Nun, nicht genau. Anfangs lief der Code nur in einem Web-Arbeiter, dann wurde mir erklärt, dass es nicht genug ist, da ein Arbeiter immer noch Zugriff auf einige lokale Ursprungsinstanzen hat, wie lokalen Speicher, indexeddb, usw. Also musste ich einen Arbeiter in ein Sandkasten-Iframe. Ein Worker war immer noch nützlich, um einen Thread zu erhalten und das Sperren der Seite mit einer Endlosschleife zu verhindern. Aber später sah es so aus, als ob viele Browser die Ausführung von Worker in einem Iframe unter https verbieten. Daher startet die Bibliothek nur einen Worker, wenn möglich, ansonsten läuft der Code einfach in einem Iframe. – asvd