46 Stimmen

Warum sollten exec() und eval() vermieden werden?

Ich habe das schon mehrfach an verschiedenen Stellen gesehen, aber nie eine befriedigende Erklärung dafür gefunden, warum das so sein sollte.

Deshalb wird hier hoffentlich eine vorgestellt werden. Warum sollten wir (zumindest im Allgemeinen) nicht exec() y eval() ?

EDIT: Ich sehe, dass die Leute davon ausgehen, dass sich diese Frage auf Webserver bezieht - das tut sie nicht. Ich kann verstehen, warum eine nicht sanitisierte Zeichenkette, die an exec könnte schlecht sein. Ist es schlecht in Nicht-Web-Anwendungen?

1 Stimmen

Können Sie einige Zitate von "mehreren Stellen" anführen, um zu klären, auf welche Bemerkungen Sie sich stützen? Es ist wichtig zu wissen, was Sie gelesen haben, um zu dem Schluss zu kommen, dass sie gemieden werden sollten. Das ist kein einfaches Thema, und Sie müssen Ihre Informationsquelle angeben, um Ihre Frage zu klären.

0 Stimmen

Soweit ich mich erinnere (da ich diese Orte im Laufe der Jahre nicht mit Lesezeichen versehen habe), haben die Warnungen in der Regel die Form von "Natürlich könnten wir eval() um dieses Problem zu lösen, aber das wäre unanständig."

0 Stimmen

Das jüngste Beispiel war wohl die Verwendung von exec() als Mittel zum Kontrollfluss innerhalb des Programms.

6voto

Diese Funktionen in einem Kontext zuzulassen, in dem sie Benutzereingaben ausführen könnten, ist ein Sicherheitsproblem, und tatsächlich funktionierende Sanitizer sind schwer zu schreiben.

1 Stimmen

Es ist also nur im Zusammenhang mit einer Webanwendung schlecht zu verwenden?

3 Stimmen

Sind alle Benutzer in der Kommandozeile vertrauenswürdig? Vielleicht sollten Sie sich auch darüber Gedanken machen...

3 Stimmen

Nein. Sie könnten als Teil eines Angriffs zur Ausweitung der Privilegien von jemandem verwendet werden, der keinen Root-Zugriff auf dem Rechner hat, aber Zugriff auf die Ausführung des Skripts hat.

6voto

jathanism Punkte 31729

Ich habe verwendet eval() in der Vergangenheit (und auch heute noch von Zeit zu Zeit) für das Massieren von Daten bei schnellen und schmutzigen Operationen verwendet. Es ist ein Teil des Werkzeugkastens, der für die Erledigung einer Aufgabe verwendet werden kann, sollte aber NIEMALS für etwas verwendet werden, das Sie in der Produktion einsetzen wollen wie z. B. Befehlszeilen-Tools oder Skripte, und zwar aus den in den anderen Antworten genannten Gründen.

Sie können sich nicht darauf verlassen, dass Ihre Benutzer das Richtige tun - niemals. In den meisten Fällen werden sie es tun, aber Sie müssen damit rechnen, dass sie all die Dinge tun, an die Sie nie gedacht haben, und all die Fehler finden, die Sie nie erwartet haben. Dies ist genau der Punkt, an dem eval() wird von einem Hilfsmittel zu einer Belastung.

Ein perfektes Beispiel dafür wäre die Verwendung von Django, wenn man eine QuerySet . Die Parameter, die an eine Abfrage übergeben werden, akzeptieren Schlüsselwortargumente, die etwa so aussehen:

results = Foo.objects.filter(whatever__contains='pizza')

Wenn Sie Argumente programmatisch zuweisen, könnten Sie etwa so vorgehen:

results = eval("Foo.objects.filter(%s__%s=%s)" % (field, matcher, value))

Aber es gibt immer einen besseren Weg, der nicht mit eval() was die Übergabe eines Wörterbuchs per Referenz bedeutet:

results = Foo.objects.filter( **{'%s__%s' % (field, matcher): value} ) 

Auf diese Weise ist es nicht nur leistungsmäßig schneller, sondern auch sicherer und pythonischer.

Die Moral von der Geschicht?

Verwendung von eval() es ok für kleine Aufgaben, Tests und wirklich vorübergehende Dinge, aber schlecht für eine dauerhafte Nutzung, denn es gibt fast immer einen besseren Weg, dies zu tun!

0 Stimmen

+1 für die Mitteilung, dass die Verwendung von eval() ist in selbst geschriebenen Skripten völlig in Ordnung.

1 Stimmen

Solange, bis die besagten selbst entwickelten Skripte das Nest verlassen und weit verbreitet sind, was sie in der Regel auch tun.

0 Stimmen

Wenn Sie jemals das Decorator-Modul in der Produktion verwendet haben (wie auch eine Menge anderer Bibliotheken), haben Sie exec in der Produktion verwendet. exec und eval sind für viele Dinge nützlich, außer für die Dateneingabe durch einen Endbenutzer.

5voto

Azeem.Butt Punkte 6025

Das ist auch der Grund, warum man sich nicht als Root anmelden sollte: Man schießt sich zu leicht in den Fuß.

5 Stimmen

Und, was vielleicht noch wichtiger ist, dass jemand anderes Ihnen in den Fuß schießt. Oder in den Kopf. Oder einfach das ganze Gebäude in die Luft jagt.

4voto

Chris Punkte 1113

Versuchen Sie nicht, die folgenden Schritte auf Ihrem Computer durchzuführen:

s = "import shutil; shutil.rmtree('/nonexisting')"
eval(s)

Nehmen wir nun an, jemand kann s beispielsweise von einer Webanwendung aus steuern.

6 Stimmen

Nur zu Ihrer Information: Das funktioniert nicht. Sie können nur einen Ausdruck in eine eval-Anweisung einbetten. Das bettet zwei Anweisungen ein.... Es könnte sogar eine Warnung nötig sein, denn ich habe gerade festgestellt, dass ich diese beiden Zeilen auf meinem Computer ausprobiert habe :-/

2 Stimmen

Was ist mit __import__("shutil").rmtree, das ist ein einzelner Ausdruck

11 Stimmen

"__import__('shutil').rmtree('/')" ist die Variante, die "funktioniert" - es ist ein einziger Ausdruck, also eval wird Ihr Dateisystem fröhlich zerstören (wenn das Programm mit ausreichenden Rechten läuft).

4voto

Rushyo Punkte 7257

Grund Nr. 1: Eine Sicherheitslücke (d.h. Programmierfehler... und wir können nicht behaupten, dass diese vermieden werden können) und Sie haben dem Benutzer gerade Zugang zur Shell des Servers gegeben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X