¿Siempre es seguro usar `eval echo`?

20

El uso a evalmenudo se desaconseja porque permite la ejecución de código arbitrario. Sin embargo, si usamos eval echo, entonces parece que el resto de la cadena se convertirá en argumentos, por echolo que debería ser seguro. ¿Estoy en lo correcto en esto?

Cyker
fuente
1
no siempre seguro, podría envolver una bomba tenedor o desagradable rm -fR *
μολὼν.λαβέ
Tal vez esto sea solo un experimento mental, pero si realmente estaba pensando en hacer esto para pasarle múltiples argumentos -n, puede hacerlo con una variable sin comillas como echo $argumentso si $argumentses una matriz echo "${arguments[@]}". El uso no eval echotiene sentido, incluso si fuera seguro.
JoL

Respuestas:

40

Contraejemplo:

DANGEROUS=">foo"
eval echo $DANGEROUS

Los argumentos arbitrarios echopodrían haber hecho algo más nefasto que crear un archivo llamado "foo".

Celada
fuente
66
Además: DANGEROUS="hello;ls"para comandos arbitrarios en lugar de ls.
Kusalananda
2
Además: DANGEROUS='$(ls)'(puede ser necesario escapar más).
wizzwizz4
Funcionaria eval echo '"'"$DANGEROUS"'"'? Parece que en goo.gl/L2pPQP
Ismael Miguel
@IsmaelMiguel Eso no funciona para los ejemplos de wizzwizz, Cyker o sorontar, o para cualquier cosa con comillas dobles en la cadena (por ejemplo DANGEROUS='">foo"').
Gordon Davisson
Maldito. Pensé que encontré algo que ayudó un poco
Ismael Miguel
26

@Celada ha proporcionado una excelente respuesta. Para demostrar evales realmente malo, aquí hay algo más nefasto que crear un archivo llamado "foo" :

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

Y, por supuesto, puede haber algo más nefasto que algo más nefasto que crear un archivo llamado "foo" .

Cyker
fuente
8
¡+1 por demostrar que citar la variable como en "$THIS"lugar de simplemente tenerla como $THISsi ni siquiera ayuda!
Celada
Enviar un par adicional de citas parece ayudar. Algo así como eval echo '"'"$DANGEROUS"'"'. Pruébalo en goo.gl/L2pPQP
Ismael Miguel
En realidad, su ejemplo no es más nefasto que >foo, porque "crear un archivo llamado 'foo'" no es necesariamente todo lo que >foohace. La única diferencia real que tiene su ejemplo es que no deja un archivo vacío. Los contenidos aún se han ido.
flarn2006
12

No, no siempre es seguro. Una evaluación podría ejecutar cualquier comando.

Un comando seguro, como este (la fecha no se ejecuta ya que está entre comillas simples):

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

Se vuelve peligroso si se usa con eval:

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

Por supuesto, la fecha podría ser cualquier comando.

Una forma de mejorar esto es citar adicionalmente los argumentos para evaluar:

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

Pero generalmente es difícil citar correctamente dos veces una expresión.

Y se vuelve imposible controlar la cita correcta si un atacante externo puede establecer la expresión, como:

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

Si bien es cierto que evalsiempre se debe abordar con precaución, la eval echoconstrucción no siempre es inútil y se puede usar de manera segura. Recientemente lo necesitaba para evaluar múltiples expansiones de llaves en el orden en que las necesitaba.

bash realiza expansiones de llaves múltiples de izquierda a derecha, entonces

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

se expande a

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

pero necesitaba la segunda expansión de llaves primero, produciendo

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

Lo mejor que se me ocurrió hacer fue

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

Esto funciona porque las comillas simples protegen el primer conjunto de llaves de la expansión durante el análisis de la evallínea de comando, dejándolos expandidos por la subshell invocada por eval.

Puede haber algún esquema astuto que implique expansiones de llaves anidadas que permita que esto suceda en un solo paso, pero si es así, soy demasiado viejo y estúpido para verlo. También hay otros depósitos bashque permiten formas más ordenadas de lograr este tipo de cosas. Pero, en cualquier caso, este uso de evales seguro porque sus argumentos son cadenas fijas que no contienen expansiones de parámetros.

Flabdablet
fuente
No necesita echo y la sustitución del comando aquí (que también depende de $ IFS). Podrías hacerloeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
Eso también funciona, pero hace que el proceso de subshell generado por eval permanezca hasta que el proceso de xargs finalice; la versión eval echo hace que esa subshell desaparezca incluso antes de que se inicie xargs. Esto probablemente solo sea importante para otras personas que son tan anales como yo acerca de lo que aparece en las vistas de árbol de htop y establece -x registros :-)
flabdablet