Wann (wenn überhaupt) ist eval NICHT böse?

Lesezeit: 8 Minuten

Wann wenn uberhaupt ist eval NICHT bose
Kendall Hopkins

Ich habe viele gehört setzt dass PHP ist eval Funktion ist oft nicht die Antwort. Angesichts von PHP 5.3 LSB und Schließungen uns gehen die Gründe aus, auf die wir uns verlassen können eval oder create_function.

Gibt es irgendein denkbare Fälle wo eval ist die beste (einzige?) Antwort in PHP 5.3?

Diese Frage ist nicht darüber ob eval ist im Allgemeinen böse, was offensichtlich nicht der Fall ist.

Zusammenfassung der Antworten:

  • Auswerten von numerischen Ausdrücken (oder anderen “sicheren” Teilmengen von PHP)
  • Unit-Tests
  • Interaktive PHP-“Shell”
  • Deserialisierung von Trusted var_export
  • Einige Vorlagensprachen
  • Erstellen von Backdoors für Administratoren und/oder Hacker
  • Kompatibilität mit < PHP 5.3
  • Überprüfung der Syntax (möglicherweise nicht sicher)

  • Wenn Sie eine fest codierte Zeichenfolge ohne Variablen auswerten. Darum geht es natürlich nicht eval() 😉

    – BoltClock

    17. August 2010 um 8:57 Uhr

  • Nach einigem Nachdenken musste ich zu dem Schluss kommen, dass ich wirklich keine gültige Verwendung von kenne eval Abgesehen vom Ausführen von kompiliertem Code oder dem Erstellen einer Try-PHP-Code-Sandbox. Daher gebe ich Kopfgeld, um entweder zu dem Schluss zu kommen, dass es seit PHP 5.3 wirklich keine Verwendung mehr für gibt eval mehr (abgesehen von Compilation/Sandbox) oder um ein gutes Beispiel dafür zu bekommen, wo man es verwenden kann.

    – Nikic

    2. November 2010 um 16:07 Uhr

  • @netcoder: Sie scheinen mir alle mehr oder weniger gleich zu sein.

    – El Yobo

    4. November 2010 um 21:40 Uhr

  • @netcoder Alle Fragen bedeuten (für mich) effektiv: “Wann ist eval die Best-Practice-Lösung.”

    – Kendall Hopkins

    4. November 2010 um 21:57 Uhr

  • @Oliver call_user_func_array klingt wie es für Sie funktionieren würde. Grundsätzlich call_user_func_array( "func", array( $arg1, ... $argn ) ) == func( $arg1, ... $argn ).

    – Kendall Hopkins

    8. Januar 2011 um 0:31 Uhr

Wenn Sie Malware schreiben und dem Systemadministrator das Leben schwer machen wollen, der versucht, hinter Ihnen aufzuräumen. Das scheint meiner Erfahrung nach der häufigste Anwendungsfall zu sein.

1646314449 348 Wann wenn uberhaupt ist eval NICHT bose
Russell Dias

Erich Lippert Summen aus drei Blogbeiträgen. Es ist eine sehr interessante Lektüre.

Soweit mir bekannt ist, sind die folgenden einige der einzigen Gründe, warum eval verwendet wird.

Zum Beispiel, wenn Sie komplexe mathematische Ausdrücke basierend auf Benutzereingaben erstellen oder wenn Sie den Objektstatus in eine Zeichenfolge serialisieren, damit er gespeichert oder übertragen und später wiederhergestellt werden kann.

  • Das Auswerten mathematischer Ausdrücke (nachdem sie auf syntaktische Korrektheit überprüft und sichergestellt wurden, dass sie nicht böswillig sind) ist wahrscheinlich wirklich eine der zulässigen Verwendungen für eval. Es selbst zu implementieren wäre zu viel des Guten. Aber zum Serialisieren von Objekten sollten Sie PHP verwenden serialize Funktion, die a) schneller b) sicherer und c) vollständiger ist (Kreisverweise, …)

    – Nikic

    4. November 2010 um 14:42 Uhr

  • Ich stimme dem zu serialize; Diese Antwort war eher aus sprachagnostischer Sicht.

    – Russel Dias

    4. November 2010 um 21:18 Uhr

  • Ich bin mir nicht sicher, ob ich zustimme, dass die Implementierung einer Engine für mathematische Ausdrücke übertrieben ist. Wenn Sie sich bemühen, sicherzustellen, dass es gültig ist, sollte es nicht zu viel mehr Aufwand sein, es zu bewerten.

    – Kendall Hopkins

    4. November 2010 um 22:01 Uhr

  • @Kendall: Klick (ist deutsch, man sollte aber zumindest den Code verstehen). Das PCRE, das ich dort verwende, ist vielleicht nicht gerade trivial zu verstehen, aber zumindest nimmt der gesamte Code nur drei Zeilen ein. Dann fange ich an, über die syntaktische Validierung (auch nicht semantisch, das macht das PCRE!) mit dem Tokenizer zu sprechen. Und nur die Liste der gültigen Token allein übersteigt die einfache regex+eval-Lösung. Also, sicher, es ist viel weniger Aufwand, zumindest wenn Sie genug mit Regex vertraut sind.

    – Nikic

    5. November 2010 um 7:41 Uhr

  • Ist das De-Fangen der Eingabe nicht fast so schwierig (und gefährlicher als) das Schreiben eines Ausdrucksauswertungsprogramms?

    – Mike Clark

    9. November 2010 um 15:54 Uhr

1646314450 214 Wann wenn uberhaupt ist eval NICHT bose
Gordon

Das Hauptproblem mit eval ist es ein Einfallstor für bösartigen Code? Daher sollten Sie es niemals in einem Kontext verwenden, in dem es von außen ausgenutzt werden kann, z. B. durch Benutzereingaben.

Ein gültiger Anwendungsfall wäre Mocking Frameworks.

Beispiel aus PHPUnit_Framework_TestCase::getMock()

// ... some code before

    $mock = PHPUnit_Framework_MockObject_Generator::generate(
      $originalClassName,
      $methods,
      $mockClassName,
      $callOriginalClone,
      $callAutoload
    );

    if (!class_exists($mock['mockClassName'], FALSE)) {
        eval($mock['code']);
    }

// ... some code after

In der generate-Methode passiert tatsächlich eine Menge Dinge. Laienhaft ausgedrückt: PHPUnit wird die Argumente übernehmen generate und erstellen Sie daraus eine Klassenvorlage. Es wird dann eval diese Klassenvorlage, um sie für die Instanziierung verfügbar zu machen. Der Punkt dabei ist natürlich, TestDoubles zu haben, um Abhängigkeiten in UnitTests zu simulieren.

1646314451 243 Wann wenn uberhaupt ist eval NICHT bose
ts.

Sie können eval verwenden, um Ad-hoc-Klassen zu erstellen:

function myAutoLoad($sClassName){

   # classic part
   if (file_exists($sClassName.'.php'){

      require $sClassName.'.php';

    } else {

      eval("
            class $sClassName{
                public function __call($sMethod,$aArgs){
                     return 'No such class: ' . $sClassName;
                 }
                }");

    }

} 

Obwohl die Verwendung natürlich ziemlich begrenzt ist (einige APIs oder vielleicht DI-Container, Test-Frameworks, ORMs, die mit Datenbanken mit dynamischer Struktur umgehen müssen, Code-Spielplätze)

Wenn Sie eine Site schreiben, die PHP-Code interpretiert und ausführt, wie es eine interaktive Shell tun würde.

Ich bin ein Systemtyp, das ist alles, was ich habe.

  • Diese Art von Anwendung wäre schwer zu sandboxen (wenn überhaupt möglich) und würde verfügen über um Administratorzugriff zu benötigen. Wenn der Benutzer Administratorzugriff haben muss, gibt es wenig bis gar keinen Grund für ihn, nicht einfach a zu bearbeiten .php Dateien direkt oder starten php -a.

    – Kendall Hopkins

    17. August 2010 um 6:08 Uhr


  • @Ken Ich sehe nicht, was “Administratorzugriff” hier mit irgendetwas zu tun hat.

    – Artefakt

    17. August 2010 um 6:24 Uhr


  • try-python.mired.org ruby.ch/interpreter/rubyinterpreter.shtml blog.arpitnext.com/2009/08/… – dort sind drei

    – Ed S.

    20. August 2010 um 20:50 Uhr

  • @Ed Swangren Die sind nicht für PHP.

    – Kendall Hopkins

    2. November 2010 um 17:39 Uhr

  • Was macht das schon? Das Konzept ist das gleiche.

    – Ed S.

    2. November 2010 um 17:57 Uhr

eval ist ein Konstrukt, das verwendet werden kann, um nach Syntaxfehlern zu suchen.

Angenommen, Sie haben diese beiden PHP-Skripte:

script1.php

<?php
// This is a valid syntax
$a = 1;

script2.php

<?php
// This is an invalid syntax
$a = abcdef

Sie können mit auf Syntaxfehler prüfen eval:

$code1 = 'return true; ?>'.file_get_contents('script1.php');
$code2 = 'return true; ?>'.file_get_contents('script2.php');

echo eval($code1) ? 'script1 has valid syntax' : 'script1 has syntax errors';
echo eval($code2) ? 'script2 has valid syntax' : 'script2 has syntax errors';

nicht wie php_check_syntax (was sowieso veraltet und entfernt ist), wird der Code nicht ausgeführt.

BEARBEITEN:

Die andere (bevorzugte) Alternative ist php -l. Sie können die obige Lösung verwenden, wenn Sie keinen Zugriff auf system()- oder Shell-Ausführungsbefehle haben.

Diese Methode kann Klassen/Funktionen in Ihren Code einfügen. Achten Sie darauf, a durchzusetzen preg_replace anrufen oder a namespace davor, um zu verhindern, dass sie in nachfolgenden Aufrufen ausgeführt werden.

Zum OP-Thema: Wann (wenn überhaupt) ist eval NICHT böse? eval ist einfach nicht böse. Programmierer sind böse für die Verwendung eval ohne Grund. eval kann Ihren Code verkürzen (mathematische Ausdrucksauswertung, pro Beispiel).

  • Diese Art von Anwendung wäre schwer zu sandboxen (wenn überhaupt möglich) und würde verfügen über um Administratorzugriff zu benötigen. Wenn der Benutzer Administratorzugriff haben muss, gibt es wenig bis gar keinen Grund für ihn, nicht einfach a zu bearbeiten .php Dateien direkt oder starten php -a.

    – Kendall Hopkins

    17. August 2010 um 6:08 Uhr


  • @Ken Ich sehe nicht, was “Administratorzugriff” hier mit irgendetwas zu tun hat.

    – Artefakt

    17. August 2010 um 6:24 Uhr


  • try-python.mired.org ruby.ch/interpreter/rubyinterpreter.shtml blog.arpitnext.com/2009/08/… – dort sind drei

    – Ed S.

    20. August 2010 um 20:50 Uhr

  • @Ed Swangren Die sind nicht für PHP.

    – Kendall Hopkins

    2. November 2010 um 17:39 Uhr

  • Was macht das schon? Das Konzept ist das gleiche.

    – Ed S.

    2. November 2010 um 17:57 Uhr

Wann wenn uberhaupt ist eval NICHT bose
cwallenpoole

Ich habe festgestellt, dass es Zeiten gibt, in denen die meisten Funktionen einer Sprache nützlich sind. Immerhin sogar GOTO hat seine Befürworter. Eval wird in einer Reihe von Frameworks verwendet und wird gut verwendet. Beispielsweise verwendet CodeIgniter eval um zwischen der Klassenhierarchie von PHP 4- und PHP 5-Implementierungen zu unterscheiden. Blog-Plugins, die die Ausführung von PHP-Code ermöglichen, benötigen dies definitiv (und das ist eine Funktion, die in Expression Engine, WordPress und anderen verfügbar ist). Ich habe es auch für eine Website verwendet, auf der sich eine Reihe von Ansichten befinden schon fast identisch, aber für jeden war benutzerdefinierter Code erforderlich, und das Erstellen einer Art verrückter Regelmaschine war weitaus komplizierter und langsamer.

Obwohl ich weiß, dass dies kein PHP ist, habe ich festgestellt, dass Pythons eval die Implementierung eines einfachen Taschenrechners viel einfacher macht.

Grundsätzlich stellt sich hier die Frage:

  1. Schafft es eval einfacher zu lesen? Eines unserer Hauptziele ist es, anderen Programmierern mitzuteilen, was uns durch den Kopf ging, als wir dies schrieben. Im CodeIgniter-Beispiel ist sehr klar, was sie erreichen wollten.
  2. Gibt es eine andere Art und Weise? Die Chancen stehen gut, wenn Sie verwenden eval (oder Variablen-Variablen oder jede andere Form der String-Suche oder Reflection-Syntax), gibt es einen anderen Weg, dies zu tun. Haben Sie Ihre anderen Optionen ausgeschöpft? Haben Sie einen einigermaßen begrenzten Eingabesatz? Kann eine switch-Anweisung verwendet werden?

Andere Überlegungen:

  1. Kann es sicher gemacht werden? Gibt es eine Möglichkeit, dass sich ein verirrter Code in die eval-Anweisung einarbeiten kann?
  2. Kann es konsistent gemacht werden? Können Sie, wenn Sie einen Input erhalten, immer und konsistent den gleichen Output produzieren?

923900cookie-checkWann (wenn überhaupt) ist eval NICHT böse?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy