In all den Jahren, die ich in PHP entwickelt habe, habe ich immer gehört, dass das Verwenden eval()
böse ist.
Wäre es angesichts des folgenden Codes nicht sinnvoll, die zweite (und elegantere) Option zu verwenden? Wenn nicht, warum?
// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";
// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);
// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');
$result = array(); preg_replace_callback('#^enum\s*\(\s*\'|\'\s*\)\s*$#', function($m) use($result) { $result[] = $m[1]; }, $type);
Antworten:
Ich würde vorsichtig sein, wenn ich eval () als reines Übel bezeichne. Die dynamische Auswertung ist ein leistungsstarkes Werkzeug und kann manchmal lebensrettend sein. Mit eval () kann man Mängel von PHP umgehen (siehe unten).
Die Hauptprobleme mit eval () sind:
Das Hauptproblem bei der tatsächlichen Verwendung von eval () ist nur eines:
Als Faustregel neige ich dazu, Folgendes zu befolgen:
quelle
eval ist böse, wenn nur die geringste Möglichkeit besteht, dass Benutzereingaben in der ausgewerteten Zeichenfolge enthalten sind. Wenn Sie ohne Inhalte von einem Benutzer auswerten, sollten Sie sicher sein.
Trotzdem sollten Sie mindestens zweimal überlegen, bevor Sie eval verwenden. Es sieht täuschend einfach aus, aber mit Blick auf die Fehlerbehandlung (siehe VBAssassins-Kommentar), die Debugbarkeit usw. ist es nicht mehr so einfach.
Als Faustregel also: Vergiss es. Wenn eval die Antwort ist, stellen Sie wahrscheinlich die falsche Frage! ;-);
quelle
eval()
es unmöglich ist, die Verwendung von zu vermeiden. Dies ist ein besserer Ansatz. Viele Leute sagen, dass dieseval()
in einigen Fällen unvermeidlich ist, aber sie erwähnen keine konkreten Beispiele, die wir argumentieren könnten - auf diese Weise macht diese Debatte keinen Sinn. Also bitte, Leute, die sageneval()
, dass es unvermeidlich ist, beweisen es zuerst!eval () ist zu jeder Zeit gleich böse.
"Wann ist eval () nicht böse?" ist meiner Meinung nach die falsche Frage, denn es scheint zu implizieren, dass die Nachteile der Verwendung von eval () in einigen Kontexten auf magische Weise verschwinden.
Die Verwendung von eval () ist im Allgemeinen eine schlechte Idee, da dadurch die Lesbarkeit des Codes, die Möglichkeit, den Codepfad (und mögliche Auswirkungen auf die Sicherheit) vor der Laufzeit vorherzusagen, und damit die Fähigkeit zum Debuggen von Code verringert werden. Die Verwendung von eval () kann auch verhindern, dass der ausgewertete Code und der ihn umgebende Code durch einen Opcode-Cache wie den in PHP 5.5 und höher integrierten Zend Opcache oder durch einen JIT-Compiler wie den in HHVM optimiert werden.
Darüber hinaus gibt es keine Situation, für die es unbedingt erforderlich ist, eval () zu verwenden - PHP ist ohne es eine voll funktionsfähige Programmiersprache.
Ob Sie diese tatsächlich als Übel ansehen oder in einigen Fällen die Verwendung von eval () persönlich rechtfertigen können, liegt bei Ihnen. Für einige sind die Übel zu groß, um sie jemals zu rechtfertigen, und für andere ist eval () eine praktische Abkürzung.
Wenn Sie jedoch eval () als böse ansehen, ist es jederzeit böse. Es verliert nicht auf magische Weise seine Bösartigkeit je nach Kontext.
quelle
In diesem Fall ist eval wahrscheinlich sicher genug, solange ein Benutzer niemals beliebige Spalten in einer Tabelle erstellen kann.
Eleganter ist es allerdings nicht. Dies ist im Grunde ein Problem beim Parsen von Text, und der Missbrauch des PHP-Parsers scheint etwas hackig zu sein. Wenn Sie Sprachfunktionen missbrauchen möchten, missbrauchen Sie den JSON-Parser. Zumindest mit dem JSON-Parser gibt es überhaupt keine Möglichkeit der Code-Injektion.
Ein regulärer Ausdruck ist wahrscheinlich der naheliegendste Weg. Sie können einen einzelnen regulären Ausdruck verwenden, um alle Werte aus dieser Zeichenfolge zu extrahieren:
quelle
eval()
ist langsam, aber ich würde es nicht böse nennen.Es ist der schlechte Gebrauch, den wir davon machen, der zur Code-Injektion führen und böse sein kann.
Ein einfaches Beispiel:
Ein harmloses Beispiel:
Ich würde Ihnen raten, nicht zu verwenden,
eval()
aber wenn Sie dies tun, stellen Sie sicher, dass Sie alle Eingaben validieren / auf die Whitelist setzen.quelle
Wenn Sie fremde Daten (z. B. Benutzereingaben) innerhalb der Auswertung verwenden.
In Ihrem obigen Beispiel ist dies kein Problem.
quelle
Ich werde den Inhalt hier offen stehlen:
blog.joshuaeichorn.com: using-eval-in-php
quelle
eval()
ist immer böse.quelle
eval()
: Ich würde genauso schnell annehmen, dass ich die Frage falsch gestellt habe. selten ist es die "richtige" Antwort, aber im pauschalen Zustand ist es immer böse, es ist einfach falsch.Ich würde auch die Leute berücksichtigen, die Ihren Code pflegen.
eval () ist nicht einfach anzusehen und zu wissen, was passieren soll. Ihr Beispiel ist nicht so schlecht, aber an anderen Orten kann es ein richtiger Albtraum sein.
quelle
Persönlich denke ich, dass Code immer noch ziemlich böse ist, weil Sie nicht kommentieren, was er tut. Es testet auch nicht seine Eingaben auf Gültigkeit, was es sehr zerbrechlich macht.
Ich bin auch der Meinung, dass 95% (oder mehr) der Eval-Anwendungen aktiv gefährlich sind und die geringe potenzielle Zeitersparnis, die sie in anderen Fällen bieten könnte, es nicht wert ist, sich der schlechten Praxis der Verwendung zu widmen. Außerdem müssen Sie Ihren Schergen später erklären, warum Ihre Verwendung von eval gut und ihre schlecht ist.
Und natürlich sieht dein PHP wie Perl aus;)
Es gibt zwei Hauptprobleme bei eval () (als "Injektionsangriff" -Szenario):
1) Es kann Schaden anrichten. 2) Es kann einfach abstürzen
und eine, die mehr sozial als technisch ist:
3) Es wird Leute dazu verleiten, es unangemessen als Abkürzung an anderer Stelle zu verwenden
Im ersten Fall laufen Sie Gefahr (natürlich nicht, wenn Sie eine bekannte Zeichenfolge bewerten), dass beliebiger Code ausgeführt wird. Ihre Eingaben sind jedoch möglicherweise nicht so bekannt oder fest wie Sie denken.
Wahrscheinlicher (in diesem Fall) stürzt Sie einfach ab und Ihre Zeichenfolge wird mit einer unbegründet undurchsichtigen Fehlermeldung beendet. Meiner Meinung nach sollte der gesamte Code so ordentlich wie möglich fehlschlagen. Andernfalls sollte eine Ausnahme ausgelöst werden (als die am besten behandelbare Form des Fehlers).
Ich würde vorschlagen, dass Sie in diesem Beispiel eher durch Zufall als durch Verhalten codieren. Ja, die SQL-Enum-Anweisung (und sind Sie sicher, dass das Feld enum ist? - Haben Sie das richtige Feld der richtigen Tabelle der richtigen Version der Datenbank aufgerufen? Hat sie tatsächlich geantwortet?) Sieht in PHP wie eine Array-Deklarationssyntax aus. Ich würde jedoch vorschlagen, dass Sie nicht den kürzesten Weg von der Eingabe zur Ausgabe finden, sondern die angegebene Aufgabe angehen:
Das ist ungefähr die Option, die Sie wählen, aber ich würde einige Wenn und Kommentare aus Gründen der Klarheit und Sicherheit umschließen (z. B. wenn die erste Übereinstimmung nicht übereinstimmt, eine Ausnahme auslösen oder ein Nullergebnis setzen).
Es gibt immer noch einige mögliche Probleme mit Kommas oder Anführungszeichen, und Sie sollten die Daten wahrscheinlich entpacken und dann in Anführungszeichen setzen, aber Daten werden zumindest als Daten und nicht als Code behandelt.
Mit der preg_version ist Ihr schlechtestes Ergebnis wahrscheinlich $ result = null, mit der eval-Version ist das schlechteste unbekannt, aber zumindest ein Absturz.
quelle
eval wertet eine Zeichenfolge als Code aus. Das Problem dabei ist, dass die Zeichenfolge, wenn sie in irgendeiner Weise "verdorben" ist, enorme Sicherheitsbedrohungen aufdecken kann. Normalerweise liegt das Problem in einem Fall vor, in dem Benutzereingaben in der Zeichenfolge ausgewertet werden. In vielen Fällen könnte der Benutzer Code eingeben (z. B. PHP oder SSI), der dann in eval ausgeführt wird. Er wird mit denselben Berechtigungen wie Ihr PHP-Skript ausgeführt und kann verwendet werden, um Informationen / Zugriff auf Ihren Server zu erhalten. Es kann ziemlich schwierig sein, sicherzustellen, dass Benutzereingaben ordnungsgemäß bereinigt werden, bevor sie an eval übergeben werden. Es gibt andere Probleme, von denen einige umstritten sind
quelle
PHP empfiehlt, dass Sie Ihren Code so schreiben, dass er über call_user_func ausgeführt werden kann, anstatt explizite Auswertungen vorzunehmen.
quelle
Ein weiterer
eval
böser Grund ist, dass es nicht von PHP-Bytecode-Caches wie eAccelertor oder ACP zwischengespeichert werden konnte.quelle
Es ist eine schlechte Programmierung, die eval () böse macht, nicht die Funktion. Ich benutze es manchmal, da ich es in der dynamischen Programmierung auf mehreren Sites nicht umgehen kann. Ich kann nicht, dass PHP an einer Site analysiert wird, da ich nicht die gewünschten Dinge erhalte. Ich würde nur ein Ergebnis erhalten! Ich bin froh, dass eine Funktion wie eval () existiert, da sie mein Leben viel einfacher macht. Benutzereingabe? Nur schlechte Programmierer werden von Hackern gefesselt. Darüber mache ich mir keine Sorgen.
quelle
Ich gehe davon aus, dass Sie bald ernsthafte Probleme haben werden ...
Ehrlich gesagt gibt es absolut keine gute Verwendung für eine exorbitante Funktion wie eval in einer interpretierten Sprache wie PHP. Ich habe noch nie gesehen, dass eval Programmfunktionen ausführt, die auf andere, sicherere Weise nicht ausgeführt werden konnten ...
Eval ist die Wurzel allen Übels, da stimme ich voll und ganz allen Menschen zu, die glauben, dass das Testen von Benutzereingaben hilfreich sein wird. Überlegen Sie zweimal, Benutzereingaben können in vielen verschiedenen Formen erfolgen, und während wir sprechen, nutzen Hacker diese Funktion, die Ihnen nicht wichtig genug war. Vermeiden Sie meiner Meinung nach die Bewertung ganz.
Ich habe handgefertigte Beispiele gesehen, um die Bewertungsfunktion zu missbrauchen, die meine eigene Kreativität übertraf. Vermeiden Sie aus Sicherheitsgründen um jeden Preis, und ich würde sogar so weit gehen, zu fordern, dass es zumindest eine Option in der PHP-Konfiguration ist und keine "gegebene".
quelle
eval
. Und deshalb ist X: X für jedes Feature die Wurzel allen Eval ... ähm ... Bösen, also geben Sie die Programmierung besser ganz auf (und ziehen Sie so den Teppich unter diesen albernen Hackern hervor und überlisten Sie sie schließlich immer noch).Hier ist eine Lösung zum Ausführen von PHP-Code aus einer Datenbank ohne Verwendung von eval. Ermöglicht alle Funktionen und Ausnahmen des Gültigkeitsbereichs:
Grundsätzlich erstellt es eine eindeutige Funktion mit dem in einer Textdatei enthaltenen Code, schließt die Datei ein, ruft die Funktion auf und entfernt die Datei, wenn sie damit fertig ist. Ich verwende dies, um tägliche Datenbankaufnahmen / Synchronisierungen durchzuführen, bei denen für jeden Schritt eindeutiger Code erforderlich ist, um verarbeitet zu werden. Dies hat alle Probleme gelöst, mit denen ich konfrontiert war.
quelle
Früher habe ich oft eval () verwendet, aber in den meisten Fällen muss eval nicht verwendet werden, um Tricks auszuführen. Nun, Sie haben call_user_func () und call_user_func_array () in PHP. Es ist gut genug, um jede Methode statisch und dynamisch aufzurufen.
Um einen statischen Aufruf durchzuführen, erstellen Sie Ihren Rückruf als Array ('Klassenname', 'Methodenname') oder sogar als einfache Zeichenfolge wie 'Klassenname :: Methodenname'. Verwenden Sie zum Ausführen eines dynamischen Aufrufs einen Rückruf im Array-Stil ($ object, 'method').
Die einzig sinnvolle Verwendung von eval () ist das Schreiben eines benutzerdefinierten Compilers. Ich habe eins gemacht, aber eval ist immer noch böse, weil es so verdammt schwer zu debuggen ist. Das Schlimmste ist, dass der schwerwiegende Fehler im ausgewerteten Code den Code zum Absturz bringt, der ihn aufgerufen hat. Ich habe die Parsekit PECL-Erweiterung verwendet, um zumindest die Syntax zu überprüfen, aber immer noch keine Freude - versuchen Sie, auf unbekannte Klassen- und ganze App-Abstürze zu verweisen.
quelle
Abgesehen von Sicherheitsbedenken kann eval () nicht kompiliert, optimiert oder im Opcode zwischengespeichert werden, daher ist es immer langsamer - viel langsamer - als normaler PHP-Code. Es ist daher nicht performant, eval zu verwenden, obwohl das es nicht böse macht. (
goto
ist böse,eval
ist nur schlechte Praxis / stinkender Code / hässlich)quelle
eval
bekommt eine niedrigere böse Bewertung alsgoto
? Ist es entgegengesetzter Tag?goto
in 5.3 implementiert haben .goto
Nein , zu den Fobianern: Es gibt die Werkzeuge und es gibt die Handwerker, die sie benutzen (oder nicht). Es sind nie die Werkzeuge, die einen Profi wie einen Idioten aussehen lassen, wenn er Fehler macht, sondern die Unfähigkeit, die richtigen Werkzeuge (richtig) zu verwenden. Aber es sind immer die Werkzeuge, die schuld sind ...Die meisten Leute werden darauf hinweisen, dass es gefährlich sein kann, wenn Sie mit Benutzereingaben arbeiten (mit denen man umgehen kann).
Für mich ist das Schlimmste, dass es die Wartbarkeit Ihres Codes verringert :
quelle