Est-il toujours sûr d'utiliser «eval echo»?

20

L'utilisation evalest souvent déconseillée car elle permet l'exécution de code arbitraire. Cependant, si nous l'utilisons eval echo, il semble que le reste de la chaîne deviendra des arguments, echodonc cela devrait être sûr. Ai-je raison là-dessus?

Cyker
la source
1
pas toujours sûr, vous pouvez envelopper une bombe à fourche ou une mauvaise rm -fR *
μολὼν.λαβέ
Peut-être que ce n'est qu'une expérience de pensée, mais si vous envisagiez de faire cela pour lui passer plusieurs arguments comme -n, vous pouvez simplement le faire avec une variable non citée comme echo $argumentsou si $argumentsc'est un tableau echo "${arguments[@]}". L'utilisation eval echoest inutile même si elle était sûre.
JoL

Réponses:

40

Contre-exemple:

DANGEROUS=">foo"
eval echo $DANGEROUS

Les arguments arbitraires echoauraient pu faire quelque chose de plus néfaste que la création d'un fichier appelé "foo".

Celada
la source
6
Aussi DANGEROUS="hello;ls":, pour les commandes arbitraires à la place de ls.
Kusalananda
2
Aussi: DANGEROUS='$(ls)'(plus d'échappement peut être nécessaire).
wizzwizz4
Ça eval echo '"'"$DANGEROUS"'"'marcherait? Il semble sur goo.gl/L2pPQP
Ismael Miguel
@IsmaelMiguel Cela ne fonctionne pas pour les exemples de wizzwizz, Cyker ou sorontar, ni pour quoi que ce soit avec des guillemets doubles dans la chaîne (par exemple DANGEROUS='">foo"').
Gordon Davisson
Zut. Je pensais avoir trouvé quelque chose qui m'a aidé un peu
Ismael Miguel
26

@Celada a fourni une excellente réponse. Démontrer que evalc'est vraiment mal, voici quelque chose de plus néfaste que de créer un fichier appelé "foo" :

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

Et bien sûr, il peut y avoir quelque chose de plus néfaste que quelque chose de plus néfaste que de créer un fichier appelé "foo" .

Cyker
la source
8
+1 pour avoir démontré que citer la variable comme "$THIS"au lieu de simplement l'avoir comme $THISn'aide pas du tout!
Celada
L'envoi d'une paire supplémentaire de devis semble aider. Quelque chose comme eval echo '"'"$DANGEROUS"'"'. Essayez-le sur goo.gl/L2pPQP
Ismael Miguel
En fait, votre exemple n'est pas plus néfaste que cela >foo, car «créer un fichier appelé 'foo'» n'est pas nécessairement tout ce qui se >foopasse. La seule vraie différence de votre exemple est qu'il ne laisse pas de fichier vide derrière. Le contenu est toujours parti.
flarn2006
12

Non c'est pas toujours sûr. Un eval pourrait exécuter n'importe quelle commande.

Une commande sûre, comme celle-ci (la date n'est pas exécutée car elle est entre guillemets simples):

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

Devient dangereux s'il est utilisé avec eval:

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

Bien sûr, la date pourrait être n'importe quelle commande.

Une façon d'améliorer cela est de citer également les arguments à eval:

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

Mais il est généralement difficile de citer correctement deux fois une expression.

Et il devient impossible de contrôler la citation correcte si l'expression peut être définie par un attaquant externe, comme:

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

S'il est vrai que cela evaldoit toujours être abordé avec prudence, la eval echoconstruction n'est pas toujours inutile et peut être utilisée en toute sécurité. J'en avais récemment besoin pour faire évaluer plusieurs extensions d'accolade dans l'ordre où je les avais fait.

bash fait plusieurs expansions d'accolade de gauche à droite, donc

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

s'étend à

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

mais j'avais besoin que la deuxième extension de l'orthèse soit faite en premier, donnant

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

Le mieux que j'ai pu faire pour le faire était

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

Cela fonctionne parce que les guillemets simples protègent le premier ensemble d'accolades de l'expansion pendant l'analyse de la evalligne de commande, les laissant être développés par le sous-shell invoqué par eval.

Il peut y avoir un schéma astucieux impliquant des extensions d'accolades imbriquées qui permet que cela se produise en une seule étape, mais s'il y en a, je suis trop vieux et stupide pour le voir. Il y a aussi des coquilles autres que celles bashqui permettent des façons plus ordonnées de réaliser ce genre de chose. Mais dans tous les cas, cette utilisation de evalest sûre car ses arguments sont tous des chaînes fixes qui ne contiennent aucune extension de paramètre.

flabdablet
la source
Vous n'avez pas besoin d'écho et de la substitution de commandes ici (qui dépend également de $ IFS). Tu pourrais faireeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
Cela fonctionne aussi, mais cela fait que le processus de sous-shell engendré par eval reste jusqu'à ce que le processus xargs soit terminé; la version eval echo fait disparaître ce sous-shell avant même que xargs ne soit lancé. Ceci n'est probablement important que pour ceux qui sont aussi anaux que moi à propos de ce qui apparaît dans les vues d'arborescence htop et les journaux -x :-)
flabdablet