Warum ist die Verwendung der JavaScript-Bewertungsfunktion eine schlechte Idee?

534

Die Auswertungsfunktion ist eine leistungsstarke und einfache Möglichkeit, Code dynamisch zu generieren. Was sind also die Einschränkungen?

Brian Singh
quelle
92
Seien
Brian Singh
5
Wie in moduscreate.com/javascript-performance-tips-tricks - beschrieben, ist (neue Funktion (str)) () leistungsfähiger als eval (str). Nur meine 2 Cent :)
Grgur
3
anscheinend ist die neue Funktion (a) 67% langsamer als die Bewertung (a) auf Chrom
was ist Schlaf
Für mich ist neue Funktionen (a) 80% langsamer neuesten Chrom auf Osx
John Smith
3
Ich habe eine statische Funktion hinzugefügt, um die Leistung zu vergleichen. jsperf.com/eval-vs-new-function/2
Nepoxx

Antworten:

386
  1. Die unsachgemäße Verwendung von eval öffnet Ihren Code für Injektionsangriffe

  2. Das Debuggen kann schwieriger sein (keine Zeilennummern usw.)

  3. eval'd Code wird langsamer ausgeführt (keine Möglichkeit, eval'd Code zu kompilieren / zwischenzuspeichern)

Bearbeiten: Wie @Jeff Walden in den Kommentaren hervorhebt, ist # 3 heute weniger wahr als 2008. Obwohl einige kompilierte Skripte zwischengespeichert werden können, ist dies nur auf Skripte beschränkt, die ohne Änderung wiederholt werden. Ein wahrscheinlicheres Szenario ist, dass Sie Skripte bewerten, die jedes Mal geringfügig geändert wurden und daher nicht zwischengespeichert werden konnten. Sagen wir einfach, dass EINIGER ausgewerteter Code langsamer ausgeführt wird.

Prestaul
quelle
2
@ JeffWalden, toller Kommentar. Ich habe meinen Beitrag aktualisiert, obwohl mir klar ist, dass es ein Jahr her ist, seit du gepostet hast. Xnzo72, wenn Sie Ihren Kommentar etwas qualifiziert hätten (wie Jeff), könnte ich Ihnen vielleicht zustimmen. Jeff wies auf den Schlüssel hin: "Durch mehrmaliges Auswerten derselben Zeichenfolge kann der Analyseaufwand vermieden werden." So wie es ist, liegst du einfach falsch; # 3 gilt für viele Szenarien.
Prestaul
7
@Prestaul: Da der vermeintliche Angreifer nur ein beliebiges Entwicklertool verwenden kann, um das JavaScript im Client zu ändern, warum öffnet Eval () Ihren Code für Injection-Angriffe? Ist noch nicht geöffnet? (Ich spreche natürlich über Client JavaScript)
Eduardo Molteni
60
@EduardoMolteni, es ist uns egal (und wir können es auch nicht verhindern), dass Benutzer js in ihren eigenen Browsern ausführen. Die Angriffe, die wir vermeiden möchten, sind, wenn vom Benutzer bereitgestellte Werte gespeichert, später in Javascript abgelegt und ausgewertet werden. Zum Beispiel könnte ich meinen Benutzernamen auf badHackerGuy'); doMaliciousThings();Folgendes setzen: Wenn Sie meinen Benutzernamen in ein Skript einbinden und ihn in den Browsern anderer Leute auswerten, kann ich jedes gewünschte Javascript auf ihren Computern ausführen (z. B. sie zwingen, +1 meiner Beiträge zu senden,
poste
3
Im Allgemeinen gilt # 1 für ziemlich viele, wenn nicht die meisten Funktionsaufrufe. eval () sollte nicht von erfahrenen Programmierern herausgegriffen und vermieden werden, nur weil unerfahrene Programmierer es missbrauchen. Erfahrene Programmierer haben jedoch häufig eine bessere Architektur in ihrem Code, und eval () wird aufgrund dieser besseren Architektur selten benötigt oder sogar in Betracht gezogen.
Frodeborli
4
@ TamilVendhan Sicher können Sie Haltepunkte setzen. Sie können auf die von Chrome erstellte virtuelle Datei für Ihren ausgewerteten Code zugreifen, indem Sie die debugger;Anweisung zu Ihrem Quellcode hinzufügen . Dadurch wird die Ausführung Ihres Programms in dieser Zeile gestoppt. Danach können Sie Debug-Haltepunkte hinzufügen, als wäre es nur eine weitere JS-Datei.
Sid
346

eval ist nicht immer böse. Es gibt Zeiten, in denen es vollkommen angemessen ist.

Allerdings wird eval derzeit und historisch von Menschen, die nicht wissen, was sie tun, massiv überstrapaziert. Dazu gehören leider auch Leute, die JavaScript-Tutorials schreiben, und in einigen Fällen kann dies tatsächlich Sicherheitsfolgen haben - oder häufiger einfache Fehler. Je mehr wir tun können, um ein Fragezeichen über die Bewertung zu werfen, desto besser. Jedes Mal, wenn Sie eval verwenden, müssen Sie überprüfen, was Sie tun, da Sie es wahrscheinlich besser, sicherer und sauberer machen könnten.

Um ein allzu typisches Beispiel zu geben, um die Farbe eines Elements mit einer ID festzulegen, die in der Variablen 'Kartoffel' gespeichert ist:

eval('document.' + potato + '.style.color = "red"');

Wenn die Autoren der oben genannten Art von Code eine Ahnung von den Grundlagen der Funktionsweise von JavaScript-Objekten hätten, hätten sie erkannt, dass eckige Klammern anstelle von wörtlichen Punktnamen verwendet werden können, sodass keine Bewertung erforderlich ist:

document[potato].style.color = 'red';

... was viel einfacher zu lesen und weniger potenziell fehlerhaft ist.

(Aber dann würde jemand, der / wirklich / wusste, was er tat, sagen:

document.getElementById(potato).style.color = 'red';

Das ist zuverlässiger als der zwielichtige alte Trick, direkt aus dem Dokumentobjekt heraus auf DOM-Elemente zuzugreifen.)

Bobince
quelle
82
Hmm, ich schätze, ich hatte Glück, als ich zum ersten Mal JavaScript lernte. Ich habe immer "document.getElementById" verwendet, um auf das DOM zuzugreifen. Ironischerweise habe ich es damals nur gemacht, weil ich keine Ahnung hatte, wie Objekte in JavaScript funktionieren ;-)
Mike Spross
5
zustimmen. Manchmal ist die
Bewertung in Ordnung,
40
@schoetbi: Solltest du nicht JSON.parse()statt eval()für JSON verwenden?
Nyuszika7h
4
@bobince code.google.com/p/json-sans-eval funktioniert in allen Browsern, ebenso wie github.com/douglascrockford/JSON-js . Doug Crockfords json2.js verwendet eval intern, jedoch mit Überprüfungen. Außerdem ist es vorwärtskompatibel mit der integrierten Browserunterstützung für JSON.
Martijn
8
@bobince Es gibt so etwas wie Feature-Erkennung und Polyfills, um fehlende JSON-Bibliotheken und andere Dinge zu behandeln (siehe modernizr.com )
MauganRa
37

Ich glaube, das liegt daran, dass es jede JavaScript-Funktion aus einem String ausführen kann. Die Verwendung erleichtert es Benutzern, unerwünschten Code in die Anwendung einzufügen.

kemiller2002
quelle
5
Was ist dann die Alternative?
Moderne
5
Wirklich ist die Alternative, einfach Code zu schreiben, der ihn nicht benötigt. Crockford geht ausführlich darauf ein, und wenn Sie es verwenden müssen, sagt er ziemlich genau, dass es ein Programmdesignfehler ist und überarbeitet werden muss. In Wahrheit stimme ich ihm auch zu. JS ist trotz aller Mängel sehr flexibel und bietet viel Platz, um es flexibel zu machen.
Kemiller2002
3
Nicht wahr, die meisten Frameworks verfügen über eine Methode zum Parsen von JSON. Wenn Sie kein Framework verwenden, können Sie JSON.parse () verwenden. Die meisten Browser unterstützen dies, und wenn Sie wirklich in Not sind, können Sie ganz einfach einen Parser für JSON schreiben.
Kemiller2002
6
Ich kaufe dieses Argument nicht, weil es bereits einfach ist, unerwünschten Code in eine Javascript-Anwendung einzufügen. Wir haben Browserkonsolen, Skripterweiterungen usw. Jeder einzelne Code, der an den Client gesendet wird, kann vom Client optional ausgeführt werden.
user2867288
6
Der Punkt ist, dass es für mich einfacher ist, Code in Ihren Browser einzufügen. Angenommen, Sie verwenden eval für eine Abfragezeichenfolge. Wenn ich Sie dazu verführe, mit angehängter Abfragezeichenfolge auf einen Link zu dieser Site zu klicken, habe ich meinen Code jetzt mit vollständiger Erlaubnis des Browsers auf Ihrem Computer ausgeführt. Ich möchte alles, was Sie auf dieser Site eingeben, mit einem Schlüssel protokollieren und an mich senden. Fertig und keine Möglichkeit, mich aufzuhalten, denn wenn eval ausgeführt wird, gibt der Browser ihm die höchste Autorität.
kemiller2002
27

Zwei Punkte fallen mir ein:

  1. Sicherheit (aber solange Sie die zu bewertende Zeichenfolge selbst generieren, ist dies möglicherweise kein Problem)

  2. Leistung: Bis der auszuführende Code unbekannt ist, kann er nicht optimiert werden. (über Javascript und Performance, sicherlich Steve Yegges Präsentation )

xtofl
quelle
9
Warum ist Sicherheit ein Problem, wenn der Kunde mit unserem Code sowieso alles tun kann, was er will? Fettaffe ?
Paul Brewczynski
2
@PaulBrewczynski, das Sicherheitsproblem tritt auf, wenn Benutzer A seinen zu verwendenden Teil des Codes evalspeichert und dieser kleine Code dann im B-Browser des Benutzers ausgeführt wird
Felipe Pereira
21

Das Übergeben von Benutzereingaben an eval () ist ein Sicherheitsrisiko, aber auch jeder Aufruf von eval () erstellt eine neue Instanz des JavaScript-Interpreters. Dies kann ein Ressourcenfresser sein.

Andrew Hedges
quelle
27
In den mehr als drei Jahren, seit ich darauf geantwortet habe, hat sich mein Verständnis dafür, was passiert, beispielsweise vertieft. Was tatsächlich passiert, ist, dass ein neuer Ausführungskontext erstellt wird. Siehe dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Andrew Hedges
20

Dies ist im Allgemeinen nur dann ein Problem, wenn Sie evale Benutzereingaben übergeben.

Mark Biek
quelle
16

Hauptsächlich ist es viel schwieriger zu warten und zu debuggen. Es ist wie ein goto. Sie können es verwenden, aber es macht es schwieriger, Probleme zu finden, und es erschwert die Personen, die möglicherweise später Änderungen vornehmen müssen.

Brian
quelle
Eval kann verwendet werden, um fehlende Metaprogrammierungsfunktionen wie Vorlagen zu ersetzen. Ich mag kompakte Generatoren viel mehr als endlose Liste von Funktionen auf Funktionen.
Schwachstellen
Solange die Zeichenfolge nicht vom Benutzer stammt oder auf den Browser beschränkt ist, den Sie verwenden können. JavaScript hat eine Menge Metaprogrammierleistung, indem es Dinge wie das Ändern von Prototypen, obj [member], Proxy, json.parse, Fenster, Dekorationsfunktionen (Adverbien) verwendet, wobei newf = Dekorator (oldf), Funktionen höherer Ordnung wie Array.prototype.map (f). Übergeben von Argumenten an andere Funktionen, Schlüsselwortargumente über {}. Können Sie mir einen Anwendungsfall nennen, in dem Sie dies nicht tun können, anstatt zu bewerten?
aoeu256
13

Beachten Sie, dass Sie eval () häufig verwenden können, um Code in einer ansonsten eingeschränkten Umgebung auszuführen. Websites für soziale Netzwerke, die bestimmte JavaScript-Funktionen blockieren, können manchmal durch Aufteilen in einen eval-Block getäuscht werden.

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

Wenn Sie also JavaScript-Code ausführen möchten , der sonst möglicherweise nicht zulässig ist ( Myspace , ich sehe Sie an ...), kann eval () ein nützlicher Trick sein.

Aus all den oben genannten Gründen sollten Sie es jedoch nicht für Ihren eigenen Code verwenden, bei dem Sie die vollständige Kontrolle haben - es ist einfach nicht erforderlich und besser in das Regal der kniffligen JavaScript-Hacks verbannt.

matt lohkamp
quelle
1
Nur den obigen Code aktualisieren .. --hi there! - muss in Anführungszeichen stehen, da es sich um eine Zeichenfolge handelt. eval ('al' + 'er' + 't (' + '"hi there!"' + ')');
Mahesh
2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Konrad Borowski
4
Huch, es gab Social-Networking-Sites, die alert () einschränkten, aber eval () erlaubten?!
Joshden
12

Sofern Sie eval () keinen dynamischen Inhalt (über CGI oder Eingabe) zulassen, ist er genauso sicher und solide wie alle anderen JavaScript-Elemente auf Ihrer Seite.

Thevs
quelle
Dies ist zwar richtig - wenn Ihr Inhalt nicht dynamisch ist, welchen Grund gibt es überhaupt, eval dafür zu verwenden? Sie können den Code einfach in eine Funktion einfügen und stattdessen aufrufen!
Periata Breatta
Nur zum Beispiel, um Rückgabewerte (JSON-ähnliche, vom Server definierte Zeichenfolgen usw.) zu analysieren, die vom Ajax-Aufruf stammen.
Thevs
2
Oh, ich verstehe. Ich würde diese als dynamisch bezeichnen, weil der Kunde nicht im Voraus weiß, was sie sind, aber ich verstehe, was Sie jetzt meinen.
Periata Breatta
7

Zusammen mit den restlichen Antworten glaube ich nicht, dass eval-Aussagen eine erweiterte Minimierung haben können.

Paul Mendoza
quelle
6

Dies ist ein mögliches Sicherheitsrisiko, hat einen anderen Ausführungsbereich und ist ziemlich ineffizient, da eine völlig neue Skriptumgebung für die Ausführung des Codes erstellt wird. Weitere Informationen finden Sie hier: eval .

Es ist jedoch sehr nützlich und kann mit Mäßigung viele gute Funktionen hinzufügen.

Tom
quelle
5

Wenn Sie nicht zu 100% sicher sind, dass der ausgewertete Code aus einer vertrauenswürdigen Quelle stammt (normalerweise Ihrer eigenen Anwendung), können Sie Ihr System auf todsichere Weise einem Cross-Site-Scripting-Angriff aussetzen.

John Topley
quelle
1
Nur wenn Ihre serverseitige Sicherheit schlecht ist. Client-seitige Sicherheit ist Unsinn.
DoubleOrt
5

Ich weiß, dass diese Diskussion alt ist, aber ich mag diesen Ansatz von Google wirklich und wollte dieses Gefühl mit anderen teilen;)

Die andere Sache ist, dass je besser du wirst, desto mehr versuchst du zu verstehen und schließlich glaubst du einfach nicht, dass etwas gut oder schlecht ist, nur weil es jemand gesagt hat :) Dies ist ein sehr inspirierendes Video , das mir geholfen hat, mehr selbst zu denken :) GUTE PRAXIS sind gut, aber benutze sie nicht sinnlos :)

op1ekun
quelle
1
Ja. Zumindest in Chrome habe ich bisher einen Anwendungsfall gefunden, der effizienter zu sein scheint. Führen Sie eine RAF aus, die bei jeder Iteration eine Zeichenfolge in einer bestimmten Variablen auswertet. Verwenden Sie ein setInterval, um nur grafisch ausgerichtete Elemente wie das Setzen von Transformationen usw. in dieser Zeichenfolge festzulegen. Ich habe viele andere Ansätze ausprobiert, z. B. das Durchlaufen von Funktionen in einem Array oder die Verwendung einer Variablen, um nur Transformationen für geänderte Elemente festzulegen. Bisher scheint dies jedoch am effizientesten zu sein. Wenn es um Animation geht, sind Ihre Augen der wahrste Test.
jdmayfield
5

Es ist nicht unbedingt so schlimm, vorausgesetzt Sie wissen, in welchem ​​Kontext Sie es verwenden.

Wenn Ihre Anwendung verwendet eval(), um ein Objekt aus einem JSON zu erstellen, das von einer XMLHttpRequest auf Ihre eigene Site zurückgekehrt ist und von Ihrem vertrauenswürdigen serverseitigen Code erstellt wurde, ist dies wahrscheinlich kein Problem.

Nicht vertrauenswürdiger clientseitiger JavaScript-Code kann sowieso nicht so viel. Vorausgesetzt, das, was Sie ausführen, eval()stammt aus einer vernünftigen Quelle, geht es Ihnen gut.

MarkR
quelle
3
Ist die Verwendung von eval nicht langsamer als nur das Parsen des JSON?
Brendan Long
@Qix - ausgeführt , dass Test in meinem Browser (Chrome 53) zeigt eval als etwas schneller als Parsing .
Periata Breatta
@PeriataBreatta Huh, seltsam. Ich wundere mich warum. Zu der Zeit, als ich kommentierte, war das nicht der Fall. Es ist jedoch nicht ungewöhnlich, dass Chrome in bestimmten Bereichen der Laufzeit von Version zu Version merkwürdige Leistungssteigerungen erzielt.
Qix - MONICA wurde
Ein kleiner alter Thread hier, aber von dem, was ich gelesen habe - ohne zu behaupten, dass ich ihn selbst zurückverfolgt habe - JSON.parse in der Tat ist evals Eingabe in der letzten Phase. In Bezug auf die Effizienz nimmt dies mehr Arbeit / Zeit in Anspruch. Aber was die Sicherheit betrifft, warum nicht einfach analysieren? eval ist ein großartiges Werkzeug. Verwenden Sie es für Dinge, die keinen anderen Weg haben. Um Funktionen über JSON zu übergeben, gibt es eine Möglichkeit, dies ohne Auswertung zu tun. Mit diesem zweiten Parameter in JSON.stringify können Sie einen Rückruf ausführen, den Sie über typeof überprüfen können, ob es sich um eine Funktion handelt. Holen Sie sich dann die .toString () der Funktion. Es gibt einige gute Artikel dazu, wenn Sie suchen.
jdmayfield
4

Dies verringert Ihr Vertrauen in die Sicherheit erheblich.

David Plumpton
quelle
4

Wenn Sie möchten, dass der Benutzer einige logische Funktionen eingibt und für UND das ODER auswertet, ist die JavaScript-Bewertungsfunktion perfekt. Ich kann zwei Zeichenfolgen und eval(uate) string1 === string2usw. akzeptieren .

Ian
quelle
Sie können auch Function () {} verwenden, aber seien Sie vorsichtig, wenn Sie diese auf dem Server verwenden, es sei denn, Sie möchten, dass Benutzer Ihren Server übernehmen, hahahah.
aoeu256
3

Wenn Sie die Verwendung von eval () in Ihrem Code entdecken, denken Sie an das Mantra „eval () ist böse“.

Diese Funktion nimmt eine beliebige Zeichenfolge und führt sie als JavaScript-Code aus. Wenn der betreffende Code im Voraus bekannt ist (zur Laufzeit nicht festgelegt), gibt es keinen Grund, eval () zu verwenden. Wenn der Code zur Laufzeit dynamisch generiert wird, gibt es oft einen besseren Weg, um das Ziel ohne eval () zu erreichen. Beispielsweise ist es besser und einfacher, nur die eckige Klammer für den Zugriff auf dynamische Eigenschaften zu verwenden:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Die Verwendung eval()hat auch Auswirkungen auf die Sicherheit, da Sie möglicherweise Code ausführen (z. B. aus dem Netzwerk), der manipuliert wurde. Dies ist ein häufiges Antimuster, wenn eine JSON-Antwort von einer Ajax-Anforderung verarbeitet wird. In diesen Fällen ist es besser, die integrierten Methoden des Browsers zu verwenden, um die JSON-Antwort zu analysieren und sicherzustellen, dass sie sicher und gültig ist. Für Browser, die nicht JSON.parse()nativ unterstützt werden, können Sie eine Bibliothek von JSON.org verwenden.

Es ist auch wichtig , dass die Weitergabe Saiten zu erinnern setInterval(), setTimeout()und der Function()Konstruktor ist, zum größten Teil, ähnlich wie bei eval()und sollte daher vermieden werden.

Hinter den Kulissen muss JavaScript die Zeichenfolge, die Sie als Programmcode übergeben, noch auswerten und ausführen:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

Die Verwendung des neuen Konstruktors Function () ähnelt eval () und sollte mit Vorsicht behandelt werden. Es könnte ein mächtiges Konstrukt sein, wird aber oft missbraucht. Wenn Sie unbedingt verwenden müssen eval(), können Sie stattdessen die Funktion new Function () in Betracht ziehen.

Es gibt einen kleinen potenziellen Vorteil, da der in new Function () ausgewertete Code in einem lokalen Funktionsbereich ausgeführt wird, sodass Variablen, die im ausgewerteten Code mit var definiert sind, nicht automatisch global werden.

Eine andere Möglichkeit, automatische Globals zu verhindern, besteht darin, den eval()Anruf in eine Sofortfunktion umzuwandeln .

12345678
quelle
Können Sie vorschlagen, wie ich einen funktionslokalen dynamischen Variablennamen ohne Auswertung auswerten könnte? Eval (und ähnliche) Funktionen sind in den meisten Sprachen, in denen sie enthalten sind, das letzte Mittel, aber manchmal ist es notwendig. Ist eine Lösung sicherer, wenn der Name einer dynamischen Variablen abgerufen wird? In jedem Fall dient Javascript selbst nicht der wirklichen Sicherheit (die Serverseite ist offensichtlich die Hauptverteidigung). Wenn Sie interessiert sind, hier ist mein Anwendungsfall von eval, den ich gerne ändern würde: stackoverflow.com/a/48294208
Regular Joe
2

Neben den möglichen Sicherheitsproblemen, wenn Sie vom Benutzer übermittelten Code ausführen, gibt es meistens einen besseren Weg, bei dem der Code nicht jedes Mal neu analysiert wird, wenn er ausgeführt wird. Anonyme Funktionen oder Objekteigenschaften können die meisten Anwendungen von eval ersetzen und sind viel sicherer und schneller.

Matthew Crumley
quelle
2

Dies kann zu einem größeren Problem werden, da die nächste Generation von Browsern die Variante eines JavaScript-Compilers aufweist. Über Eval ausgeführter Code funktioniert möglicherweise nicht so gut wie der Rest Ihres JavaScript für diese neueren Browser. Jemand sollte ein Profil erstellen.

Brian
quelle
2

Dies ist einer der guten Artikel über Eval und wie es kein Übel ist: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

Ich sage nicht, dass Sie ausgehen und eval () überall verwenden sollten. Tatsächlich gibt es nur sehr wenige gute Anwendungsfälle für die Ausführung von eval (). Es gibt definitiv Bedenken hinsichtlich der Klarheit des Codes, der Debugbarkeit und der Leistung, die nicht übersehen werden sollten. Aber Sie sollten keine Angst haben, es zu verwenden, wenn Sie einen Fall haben, in dem eval () Sinn macht. Versuchen Sie, es nicht zuerst zu verwenden, aber lassen Sie sich von niemandem erschrecken, wenn Sie glauben, Ihr Code sei anfälliger oder weniger sicher, wenn eval () ordnungsgemäß verwendet wird.

Amr Elgarhy
quelle
2

eval () ist sehr leistungsfähig und kann verwendet werden, um eine JS-Anweisung auszuführen oder einen Ausdruck auszuwerten. Bei der Frage geht es jedoch nicht um die Verwendung von eval (), sondern nur darum, wie die Zeichenfolge, die Sie mit eval () ausführen, von einer böswilligen Partei beeinflusst wird. Am Ende wird bösartiger Code ausgeführt. Mit der Macht geht eine große Verantwortung einher. Verwenden Sie es also mit Bedacht, wenn Sie es verwenden. Dies hat nicht viel mit der Funktion eval () zu tun, aber dieser Artikel enthält ziemlich gute Informationen: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Wenn Sie nach den Grundlagen von eval () suchen Schauen Sie hier: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

Phi
quelle
2

Die JavaScript Engine verfügt über eine Reihe von Leistungsoptimierungen, die während der Kompilierungsphase durchgeführt werden. Einige davon beschränken sich darauf, den Code während der Lexik im Wesentlichen statisch analysieren und vorab bestimmen zu können, wo sich alle Variablen- und Funktionsdeklarationen befinden, sodass das Auflösen von Bezeichnern während der Ausführung weniger Aufwand erfordert.

Wenn die Engine jedoch eine Auswertung (..) im Code findet, muss sie im Wesentlichen davon ausgehen, dass die gesamte Kenntnis der Position des Bezeichners ungültig ist, da sie zum Zeitpunkt der Lexierung nicht genau wissen kann, welchen Code Sie an eval (..) übergeben können. um den lexikalischen Bereich oder den Inhalt des Objekts zu ändern, an das Sie übergeben können, um einen neuen lexikalischen Bereich zu erstellen, der konsultiert werden soll.

Mit anderen Worten, im pessimistischen Sinne sind die meisten dieser Optimierungen sinnlos, wenn eval (..) vorhanden ist, sodass die Optimierungen einfach überhaupt nicht durchgeführt werden.

Das erklärt alles.

Referenz :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

hkasera
quelle
Keine Javascript-Engine kann den Code mit 100% iger Garantie nicht finden und bewerten. Daher muss es jederzeit bereit sein.
Jack Giffin
2

Das ist nicht immer eine schlechte Idee. Nehmen Sie zum Beispiel die Codegenerierung. Ich habe kürzlich eine Bibliothek namens Hyperbars geschrieben, die die Lücke zwischen Virtual-Dom und Lenker schließt . Dazu wird eine Lenkervorlage analysiert und in Hyperscript konvertiert, das anschließend von virtual-dom verwendet wird. Das Hyperskript wird zuerst als Zeichenfolge generiert und vor der Rückgabe eval()in ausführbaren Code umgewandelt. Ich habe eval()in dieser besonderen Situation das genaue Gegenteil des Bösen gefunden.

Grundsätzlich aus

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

Dazu

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

Die Leistung von eval()ist in einer solchen Situation kein Problem, da Sie die generierte Zeichenfolge nur einmal interpretieren und die ausführbare Ausgabe dann mehrmals wiederverwenden müssen.

Sie können sehen, wie die Codegenerierung erreicht wurde, wenn Sie neugierig sind .

Gesehen
quelle
2

Ich würde sogar sagen, dass es nicht wirklich wichtig ist, wenn Sie eval()Javascript verwenden, das in Browsern ausgeführt wird. * (Einschränkung)

Alle modernen Browser verfügen über eine Entwicklerkonsole, in der Sie ohnehin beliebiges Javascript ausführen können, und jeder semi-intelligente Entwickler kann sich Ihre JS-Quelle ansehen und alles, was er benötigt, in die Entwicklungskonsole einfügen, um das zu tun, was er möchte.

* Solange Ihre Serverendpunkte die korrekte Validierung und Bereinigung der vom Benutzer angegebenen Werte aufweisen, sollte es keine Rolle spielen, was in Ihrem clientseitigen Javascript analysiert und ausgewertet wird.

Wenn Sie jedoch fragen, ob es für die Verwendung eval()in PHP geeignet ist , lautet die Antwort NEIN , es sei denn, Sie führen Werte auf die Whitelist , die möglicherweise an Ihre Bewertung übergeben werden.

Adam Copley
quelle
Es gibt nicht nur eine Entwicklungskonsole, Sie können auch Javascript eingeben: Code in der URL-Leiste, um Ihre eigene Entwicklungskonsole auf der Seite zu erstellen, wenn keine vorhanden ist, wie dies bei alten IE-Browsern und Mobilgeräten der Fall ist.
Dmitry
1

Ich werde nicht versuchen, etwas zu widerlegen, was bisher gesagt wurde, aber ich werde diese Verwendung von eval () anbieten, die (soweit ich weiß) nicht anders gemacht werden kann. Es gibt wahrscheinlich andere Möglichkeiten, dies zu codieren und wahrscheinlich zu optimieren, aber dies geschieht aus Gründen der Klarheit lange und ohne Schnickschnack, um die Verwendung von eval zu veranschaulichen, für die es wirklich keine anderen Alternativen gibt. Das heißt: dynamische (oder genauer) programmgesteuert erstellte Objektnamen (im Gegensatz zu Werten).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

BEARBEITEN: Übrigens würde ich (aus allen bisher genannten Sicherheitsgründen) nicht vorschlagen, dass Sie Ihre Objektnamen auf Benutzereingaben basieren. Ich kann mir keinen guten Grund vorstellen, warum Sie das tun möchten. Trotzdem dachte ich, ich würde darauf hinweisen, dass es keine gute Idee wäre :)

Carnix
quelle
3
Dies kann getan werden namespaceToTest[namespaceParts[i]], ohne dass hier eine if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};else namespaceToTest = namespaceToTest[namespaceParts[i]];
Bewertung
1

Müllabfuhr

Die Garbage Collection des Browsers hat keine Ahnung, ob der ausgewertete Code aus dem Speicher entfernt werden kann, sodass er nur gespeichert bleibt, bis die Seite neu geladen wird. Nicht schlecht, wenn Ihre Benutzer nur in Kürze auf Ihrer Seite sind, aber es kann ein Problem für Webanwendungen sein.

Hier ist ein Skript, um das Problem zu demonstrieren

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

Etwas so Einfaches wie der obige Code bewirkt, dass eine kleine Menge Speicher gespeichert wird, bis die App stirbt. Dies ist schlimmer, wenn das ausgewertete Skript eine Riesenfunktion ist und Intervall aufgerufen wird.

JD
quelle