2014-03-19 13 views
6

ein Szenario vorstellen, in dem ich vom Benutzer bereitgestellte Javascript-Code, wie im folgenden Beispiel wollen, wo getUserResult ist eine Funktion, die einige Benutzer (nicht ich) geschrieben hat kontinuierlich aufrufen zu:Wie kann ich vom Benutzer bereitgestellten JavaScript-Code sicher im Browser ausführen?

for (var i = 0; i < N; ++i) { 
    var x = getUserResult(currentState); 
    updateState(currentState, x); 
} 

Wie kann ich ausführen, dass Art von Code in einem Browser und/oder Node.js, ohne Sicherheitsrisiken?

Allgemeiner, wie kann ich eine Javascript-Funktion ausführen, die die aktuelle Webseite oder einen anderen globalen Zustand nicht ändern oder sogar lesen darf? Gibt es so etwas wie eine "JS Virtual Machine" im Browser?

Wie stellt JSFiddle sicher, dass Sie keinen schädlichen Code ausführen können (zumindest könnte er Ihren Login-Namen phishing, führen Sie einen Bot für die Lebensdauer der Seite, wenn nicht viel schlimmere Dinge tun)? Oder stellt es das überhaupt nicht sicher?

+2

Klingt wie ein Job für [Google Caja] (https://developers.google.com/caja/). –

+0

@GeorgeStocker Ich habe meine Antwort mit der endgültigen Lösung, die ich verwende, aktualisiert. Es funktioniert im Browser, sollte auch auf Node funktionieren. – Domi

+0

mögliches Duplikat von [Wie kann ich nicht vertrauenswürdigen Code serverseitig ausführen?] (Http://stackoverflow.com/questions/10937870/how-to-run-untrusted-code-serverside) für Node.js, http://stackoverflow.com/questions/21408343/how-to-run-javascript-in-browser-sicher und sicher für den Browser –

Antwort

6

Nach vielen Überlegungen und mit Hilfe von anderen Postern in diesem Thread (vielen Dank für Ihre Hilfe!), Fand ich eine erste Reihe von Antworten auf meine Fragen.Ich schreibe meine Antwort hier jedoch neu, weil sie die Konzepte zusammenfasst und Ihnen auch einen wirklichen Code zum Experimentieren gibt. Im Allgemeinen gibt es zwei Lösungen für dieses Problem: Wir können iframe oder Worker verwenden, um Code in einer isolierten Umgebung auszuführen, so dass es unmöglich ist, die Informationen der aktuellen Seite zu lesen oder zu schreiben (was meine erste große Sicherheitsbedenken ist) . Darüber hinaus gibt es Sandbox-Ansätze wie Google Caja, die aber (standardmäßig) auch ihren Code in einem iframe ausführt.

Wie von Juan Garcia vorgeschlagen, gehe ich mit der Web-Worker-API, aber das ist nicht die vollständige Geschichte. Auch wenn der Mitarbeiter von der Hosting-Seite aus nicht direkt auf etwas zugreifen kann, gibt es dennoch einige Sicherheitsrisiken. This site lists all built-ins available in a Worker's context.

This JSFiddle zeigt eine Möglichkeit, eine Zeichenfolge außerhalb des window Kontext auszuführen, ohne durch den Server gehen zu müssen, der immer noch unsicher ist, wie in den Kommentaren darauf hingewiesen.

Ich habe auf das erweitert und eine schwarze Liste basierten Ansatz verwendet alle außerhalb Kommunikation zu deaktivieren, indem Sie Wegnehmen alle folgenden:

  • Worker
  • WebSocket
  • XMLHttpRequest
  • importScripts

Howeve r, ich arbeite gerade daran, es in einen Whitelist-Ansatz zu portieren, wie es here erklärt, um es auch für die (nahe) Zukunft sicher zu machen.

Für weitere Informationen beachten Sie bitte:

+0

Ihr aktueller Code macht * nicht * die Web-Worker-Umgebung für die Ausführung von willkürlichem Code wie in der verknüpften Thread, also sollten Sie nicht das "sicher laufenden nicht vertrauenswürdigen Code *" nennen !!! – Bergi

+0

"* Dadurch ist es unmöglich, die Informationen der aktuellen Seite zu lesen oder zu schreiben (was meine erste große Sicherheitsbedenken betrifft) *". Nein, tut es nicht. DOM-Zugriff ist erforderlich, um auf die aktuelle Seite zu schreiben, ja, Phishing würde also verhindert werden, aber zum Lesen reicht ein einfaches XHR - beachte, dass es privilegiert ist, da es von deiner Domain läuft! Das ist ein riesiges XSS/CSRF-Loch! – Bergi

+0

@Bergi Sie sollten die ganze Sache lesen: Am Ende gehe ich in Sicherheitsdetails und biete sogar einen Link zu einer vollständigen Lösung für die Sicherheit von Webarbeitern. Ich werde die Antwort ein wenig umformulieren, da, du hast Recht, es ist ein bisschen verwirrend. – Domi

6

Sie können dies mit Arbeitnehmern tun. Das Beste an Arbeitern ist, dass sie in einem anderen Prozess ausgeführt werden. Wenn also dieser Benutzercode in eine Unendlichkeitsschleife gerät, hängt die Seite nicht. Die einzige Schnittstelle mit dem Arbeiter ist eine Nachrichtenschnittstelle, so dass nur Zeichenfolgen ausgetauscht werden, was äußerst sicher ist, aber in manchen Situationen begrenzt ist.

Da nicht alle derzeit verwendeten Browser Mitarbeiter unterstützen, sind Iframes eine hilfreiche Alternative. Sie können sie in Javascript erstellen, display auf 'none' setzen, sie zum Dokument hinzufügen, die eval-Funktion aus dem iframe-contentWindow holen und dann den iframe 'zerstören', wie das Setzen von outerHTML auf '' (leere Zeichenkette). Es ist schwierig, da manchmal das Iframe-Fenster Müll sammelt, aber wenn Sie es richtig machen, haben Sie ein Eval, das ein anderes globales Objekt hat, das ein leeres Dokument enthält. Sie können dann eine Schnittstelle mit dem Code erstellen, der sie ausführt, wobei der Code global in Ihrer Seite ausgeführt wird. Die Sicherheit hängt davon ab, wie Sie diese Schnittstelle implementieren. Sie sollten Ihr globales Objekt nicht verfügbar machen, das heißt, Sie sollten die Eigenschaft 'parent' im iframe global aufheben, bevor Sie dort einen Benutzercode ausführen. Sie sollten außerdem sicherstellen, dass Sie kein Element-Objekt aus dem Seitendokument an den Code übergeben, der im globalen iframe ausgeführt wird, oder der Benutzer, der diesen Code ausführt, kann durch die parentElement-Eigenschaft im gesamten Dokument navigieren Ihre Element-Schnittstelle zum Beispiel mit Object.defineProperty. Es ist eine Menge Arbeit, es hat es einmal getan, aber es ist nicht sicher, dass es zwischen Browsern kompatibel sein wird. Zum Beispiel, wenn ich mich gut erinnere und ich keinen Fehler mache, ließ mich Chrome die Elterneigenschaft im iframe global annullieren, während ich in Safari auf einem iPad nicht konnte. Entschuldigung, ich habe momentan keinen Code, den ich mit dir teilen kann. Ich werde ihn veröffentlichen, wenn ich Zeit habe. Iframes-Skripts werden jedoch im selben Prozess wie die Seite ausgeführt, was bedeutet, dass eine Endlosschleife Ihre Seitenskripte aufhängt, und der Browser, der den Code für die Maschinenbefehle kompiliert, kann den Client os hängen (abhängig vom Browser und der os).

Drittens können Sie eine Sandbox verwenden, es gibt JavaScript-Selbstdolmetscher oder dergleichen in T.J. Crowder Kommentar Compiler, die das für Sie vereinfachen wird, aber der Nebeneffekt ist, dass es langsamer laufen wird, speziell Dolmetscher.

Ich denke, die Leute bei ECMA sollten sich weniger Sorgen über hässliche Pfeilsyntax und solche Dinge machen und eine sichere Art des Ablaufs mit verschiedenen globalen implementieren, die eine Schnittstelle ein bestimmtes Dokumentelement und seine Nachkommen aber nicht bekommen können dieses Element Eltern und Zugriff auf das Dokument. Dies wird effektiv eine Möglichkeit zum Schreiben von JavaScript-Plugins und auch sichere Werbung System ermöglichen.

+0

Wie kann ich zwischen den beiden kommunizieren? Kann ich irgendwie auf Funktionszeiger von einem Kontext zum anderen zugreifen? – Domi

+0

Bei Arbeitern verwenden Sie die asynchrone Nachrichtenschnittstelle. Verwenden Sie für den Iframe-Kontext nur synchrone Funktionsaufrufe. Interpreter oder Compiler hatten ihre eigene Schnittstelle, überprüfen Sie daher die Dokumentation. –

+0

Was ist mit Sicherheit? Gibt es keine Möglichkeit für einen Arbeiter, auf den Status des Fensters zuzugreifen? – Domi

Verwandte Themen