PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


create_function() genauso übel wie eval()?

with 19 comments

Heute mal eine Sonntagsfrage:

Ich überlege gerade wie ich ein Problem löse, bei dem ich wohl nur mit viel Aufwand drumherum komme, eval() zu benutzen. Auf der Suche nach einer Lösung fiel mir auch die Funktion create_function() ein, der man ähnlich wie eval() einen String übergeben kann, der dann beim Aufruf der erstellten Funktion ausgeführt wird.

Und nun meine Frage an euch: Sind die beiden Funktionen in der Gefährlichkeit gleichzusetzen wenn man beide mit einem String füllt, der zusammengesetzt wurde aus Usereingaben? Bei beiden kann böses passieren wenn man die Usereingaben nicht ordentlich filtert, sehe ich doch richtig oder? Seht ihr einen Vor- oder Nachteil von create_function() gegenüber eval()?

Ich frage weil eval() überall auf der Welt als böse angesehen wird, aber über create_function() redet niemand, und ich glaube bei unvorsichtiger Nutzung ist sie genauso gefährlich.

Written by Michael Kliewe

Mai 29th, 2011 at 12:54 pm

Posted in PHP

Tagged with , ,

19 Responses to 'create_function() genauso übel wie eval()?'

Subscribe to comments with RSS or TrackBack to 'create_function() genauso übel wie eval()?'.

  1. Hallo Michael,

    ich denke, mit create_function kann man auch eine Menge Mist machen, aber der entscheidende Unterschied ist, wenn du mich fragst, dass create_function eine Funktion erzeugt, also in einem anderen Kontext (aka scope) läuft, als wenn man eval() aufruft, also quasi:

    Dann hat man (der pöse H4ck0r) zwar immernoch Zugriff auf $_GET, $_POST, $GLOBALS, etc., aber zumindest auf nichts anderes mehr.

    Fabian Blechschmidt

    29 Mai 11 at 13:21

  2. filtert der einfach mein PHP weg… hmpf.

    also quasi:
    function streval($str) {
    eval($str);
    }

    Fabian Blechschmidt

    29 Mai 11 at 13:22

  3. create_function() *ist* eval(), mit ein wenig boilerplat-code. Versuche mal folgendes: create_function( $dummy, ‚} echo „Hello world!“; {‚ );

    Also: Ja. 🙂

    Kore

    29 Mai 11 at 13:57

  4. Schade, dass du deinen konkreten Anwendungsfall nicht beschrieben hast. Um solche Probleme zu umgehen würde ich generell eine kleine DSL schreiben — allerdings weiß ich nicht, ob PHP dafür die notwendigen Werkzeuge zur Verfügung stellt.

    Ansonsten hat Kore die Frage wohl schon abschließend beantwortet… 🙂

    Andre

    29 Mai 11 at 14:11

  5. Kore, du hast Recht, aber zur Vollständigkeit ein Beispiel, was zeigt, das der scope der Funktion verlassen werden kann – und das ist ECHT übel wenn ihr mich fragt.

    $a = ‚test‘;
    $test = create_function(“, ‚} echo $a; {‚);
    $test();
    // Output: test

    Fabian Blechschmidt

    29 Mai 11 at 14:13

  6. assert() führt auch noch übergebenen Code aus. Sofern aktiviert.

    Quu

    29 Mai 11 at 18:36

  7. kurz: ja create_function ist grob gesagt gleichbedeutend mit eval. aber es gibt noch mehr unbeachtete gefährliche funktionen/tricks. ich habe mal ein paar zusammengestellt: https://bitbucket.org/xandy/playground/src/tip/php/

    xAndy

    29 Mai 11 at 18:48

  8. Ja create_function ist aufjedenfall gleichzusetzten mit eval(). Aber ich verstehe nicht warum du create_function benötigst.
    Seit PHP5.3 gibt es ja die Möglichkeit von Closures Objekten.

    Damit wird die Funktion create_function überflüssig. Und wenn ich mich recht erinnere wird diese Funktion auch bald als deprecated eingestuft.

    Markus Bachmann

    29 Mai 11 at 19:04

  9. Mehr als das Gesagte zu wiederholen kann ich auch nicht.

    Interessant fände ich allerdings, wofür es benutzt werden sollte und ob hier nicht eine elegante Lösung ohne die beiden Funktionen gefunden wird.

    Guido

    29 Mai 11 at 19:57

  10. Es ist immer die Pest wenn man Benutzereingaben irgendwie ausführt. Du kannst die Benutzereingaben auch als Datei speichern und dann via include oder require einbinden/aufrufen. Wenn du die Eingabe vorher nicht ordentlich prüfst und filterst, landest du damit auch auf der Nase.
    Benutzereingaben sind demnach der Verwendung entsprechend zu filtern. Danach braucht man sich keine Gedanken mehr darüber zu machen ob eine Funktion gut oder böse ist.

    create_function scheint aber sehr speicherhungrig zu sein. Müsste man mal genauer austesten ob das eine oder andere performanter bzw. speicherschonender ist.

    Ralf

    29 Mai 11 at 20:25

  11. eval und create_function sind nicht mehr und nicht weniger gefährlich als jede andere Funktion. In den richtigen Händen total harmlos, in den falschen Händen absolut tödlich.

    Worum geht es denn? Vielleicht finden wir ja noch ne andere Lösung.

    Oliver

    29 Mai 11 at 23:22

  12. @Quu: assert() kannte ich noch garnicht…

    @Andre @Oliver & @all
    Ich schreibe morgen einen Blogbeitrag mit dem Problem, mal schauen wie man es noch lösen kann mit möglichst wenig Aufwand und ohne Hilfe von eval() und Konsorten.

    Michael Kliewe

    29 Mai 11 at 23:27

  13. > eval und create_function sind nicht mehr und nicht weniger gefährlich als jede andere Funktion

    mit Verlaub – das ist ja nun Unsinn.

    nik

    30 Mai 11 at 01:22

  14. mit Verlaub – das ist ja nun Unsinn.

    Inwiefern?

    Oliver

    30 Mai 11 at 01:25

  15. @nik:
    Würde mich auch interessieren. Wenn eval & create_function böse sind, dann sind es $_GET & $_POST auch.

    Es gibt keine bösen Funktionen. Nur blöde Programmierer.

    Ralf

    30 Mai 11 at 01:28

  16. Weder eval noch create_function sind gefährlich. Jedoch bedarf der Umgang mit ihnen großer Vorsicht, da man ansonsten große Sicherheitslücken öffnet. Ebenso der falsche Umgang mit Benutzereingaben.
    Möglicherweise sollten wir aufhören, Funktionen menschliche Eigenschaften zuzuweisen — und als Programmierer mehr Verantwortung über den Code übernehmen. Wie Ralf bereits schrieb, letztendlich ist der Programmierer und nicht die Funktion schuld.

    Andre

    30 Mai 11 at 07:12

  17. Bin ich der einzige, der die Performance der beiden Funktionen einen wichtigeren Nutzen zuspricht, als dem Sicherheitsrisiko? Wenn jemand schon sagt, dass er damit ein potenzielles Sicherheitsloch öffnet, weiß er wohl auch, wie er da ordentlich escapet um das Risiko zu minimieren. Aber:

    Mit jedem eval oder create_function wird der PHP-Parser neu angeworfen und kostet einige wichtige ms. Das mag im Einzelfall kaum ins Gewicht fallen, aber wenn man dann Schleifen darum baut und es benutzt wie normale Funktionen, kann das schon Zeit kosten. Kommt noch dazu, dass PHP keine Möglichkeit kennt Funktionen zu „löschen“. In dem Fall ist create_function noch viel böser als eval. Wenn man davon ausgeht, dass der Garbage-Collector schon alle nicht mehr referenzierten oder überschriebenen Speicherblöcke frei gibt, kann er das nicht mit Funktionen machen. Eine create_function in einer Schleife mit „nur“ 1000 Durchläufen, kann das schon locker das Speicherlimit exceeden.

    Jetzt kann man natürlich über Sinn und Unsinn einer solchen Schleife streiten, aber man sollte es trotzdem im Hinterkopf haben: create_function erstellt unzerstörbare Variablen!

    nick31

    30 Mai 11 at 11:00

  18. @nick31:
    Nein, bist du nicht. Siehe meinen ersten Kommentar. Aber danke für die Erklärung warum es so ist. Das create_function nicht gerade resourcenschonend ist, kann man recht häufig lesen. Jedoch nicht warum es so ist.

    Ralf

    30 Mai 11 at 17:20

  19. […] das mit create_function() möglich war. Sie sind auch himmelweit effizienter. create_function ist in Schleifen richtig richtig richtig übel. (Es gab dazu irgendwo eine bessere Erklärung, die finde ich nur gerade nicht. Aber die […]

Leave a Reply

You can add images to your comment by clicking here.