Ist es immer sicher, "eval echo" zu verwenden?

20

Von der Verwendung evalwird oft abgeraten, da sie die Ausführung von beliebigem Code ermöglicht. Wenn wir jedoch verwenden eval echo, sieht es so aus, als würde der Rest der Zeichenfolge zu Argumenten für werden, echoso dass es sicher sein sollte. Habe ich Recht?

Cyker
quelle
1
nicht immer sicher, dass Sie eine Gabelbombe oder böse rm -fR *
μολὼν.λαβέ
Vielleicht ist dies nur ein Gedankenexperiment, aber wenn Sie tatsächlich darüber nachgedacht haben, mehrere Argumente zu übergeben -n, können Sie dies einfach mit einer nicht zitierten Variablen wie echo $argumentsoder if $argumentsals Array tun echo "${arguments[@]}". Mit eval echosinnlos ist , selbst wenn es war sicher.
JoL

Antworten:

40

Gegenbeispiel:

DANGEROUS=">foo"
eval echo $DANGEROUS

Die willkürlichen Argumente echohätten schändlicher sein können, als eine Datei mit dem Namen "foo" zu erstellen.

Celada
quelle
6
Auch:, DANGEROUS="hello;ls"für beliebige Befehle anstelle von ls.
Kusalananda
2
Auch: DANGEROUS='$(ls)'(mehr Flucht kann erforderlich sein).
wizzwizz4
Würde eval echo '"'"$DANGEROUS"'"'funktionieren Es scheint auf goo.gl/L2pPQP
Ismael Miguel
@IsmaelMiguel Das funktioniert nicht für Wizzwizz-, Cyker- oder Sorontar-Beispiele oder für alles, was doppelte Anführungszeichen in der Zeichenfolge enthält (z DANGEROUS='">foo"'. B. ).
Gordon Davisson
Verdammt. Ich
Ismael Miguel
26

@ Celada hat eine ausgezeichnete Antwort geliefert. Zu demonstrieren evalist wirklich böse, hier ist etwas Schändlicheres als das Erstellen einer Datei mit dem Namen "foo" :

DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"

Und natürlich kann es etwas Schändlicheres als etwas Schändlicheres geben, als eine Datei namens "foo" zu erstellen .

Cyker
quelle
8
+1, um zu demonstrieren, "$THIS"dass es $THISnicht einmal hilft , die Variable mit Anführungszeichen zu versehen, anstatt sie nur so zu haben !
Celada
Das Senden eines zusätzlichen Paares von Zitaten scheint zu helfen. So etwas wie eval echo '"'"$DANGEROUS"'"'. Probieren Sie es auf goo.gl/L2pPQP
Ismael Miguel
Tatsächlich ist Ihr Beispiel nicht schändlicher als >foo, weil "Erstellen einer Datei mit dem Namen" foo "" nicht unbedingt alles ist, was das >footut. Der einzige wirkliche Unterschied, den Ihr Beispiel hat, ist, dass es keine leere Datei zurücklässt. Der Inhalt ist noch weg.
Flarn2006
12

Nein, es ist nicht immer sicher. Ein eval kann jeden Befehl ausführen.

Ein sicherer Befehl wie dieser (das Datum wird nicht ausgeführt, da es in einfachen Anführungszeichen steht):

$ echo '$(date)'
$(date)

Wird bei Verwendung mit eval gefährlich:

$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016

Natürlich kann Datum ein beliebiger Befehl sein.

Eine Möglichkeit, dies zu verbessern, besteht darin, zusätzlich die Argumente zu eval zu zitieren:

$ eval echo '\$(date)'
$(date)

Normalerweise ist es jedoch schwierig, einen Ausdruck zweimal richtig zu zitieren.

Und es wird unmöglich, das korrekte Zitieren zu kontrollieren, wenn der Ausdruck von einem externen Angreifer gesetzt werden könnte, wie zum Beispiel:

$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!
Sorontar
quelle
1

Zwar muss evalimmer mit Vorsicht vorgegangen werden, aber die eval echoKonstruktion ist nicht immer sinnlos und kann sicher verwendet werden. Ich brauchte es kürzlich, um mehrere Klammererweiterungen in der Reihenfolge zu bewerten, in der ich sie benötigte.

bash Führt mehrere Klammererweiterungen von links nach rechts durch

xargs -I_ cat _/{11..15}/{8..5}.jpg

erweitert um

xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg

aber ich musste die zweite Klammer-Erweiterung zuerst machen und nachgeben

xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg

Das Beste, was ich mir dafür einfallen lassen konnte, war

xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)

Dies funktioniert, weil die einfachen Anführungszeichen den ersten Satz von geschweiften Klammern vor einer Erweiterung während des Parsens der evalBefehlszeile schützen und sie durch die von aufgerufene Subshell erweitern lassen eval.

Möglicherweise gibt es ein ausgeklügeltes Schema mit geschachtelten Klammererweiterungen, das dies in einem Schritt ermöglicht, aber wenn es etwas gibt, bin ich zu alt und dumm, um es zu sehen. Es gibt auch andere Muscheln bash, mit denen sich solche Dinge aufgeräumter erreichen lassen. Diese Verwendung von evalist jedoch in jedem Fall sicher, da es sich bei den Argumenten um feste Zeichenfolgen handelt, die keine Parametererweiterungen enthalten.

flabdablet
quelle
Sie brauchen hier kein Echo und keine Befehlsersetzung (was auch von $ IFS abhängt). Sie könnten tuneval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
Das funktioniert auch, aber es bewirkt, dass der Subshell-Prozess durch eval herumhakt, bis der Xargs-Prozess abgeschlossen ist. die eval echo version lässt diese subshell verschwinden, bevor xargs überhaupt gestartet wird. Dies ist wahrscheinlich nur für andere wichtig, die so anal sind wie ich, was in den Ansichten von
HTML-