É sempre seguro usar o `eval echo`?

20

O uso evalgeralmente é desencorajado, pois permite a execução de código arbitrário. No entanto, se usarmos eval echo, parece que o restante da string se tornará um argumento, echoportanto deve ser seguro. Estou correto nisso?

Cyker
fonte
11
nem sempre seguro, você pode envolver uma bomba de forquilha ou desagradável rm -fR *
μολὼν.λαβέ
Talvez este seja apenas um experimento mental, mas se você realmente estava pensando em fazer isso para passar vários argumentos como -n, pode fazê-lo com uma variável não citada como echo $argumentsou se $argumentsé uma matriz echo "${arguments[@]}". Usar eval echoé inútil, mesmo que fosse seguro.
JOL

Respostas:

40

Contraexemplo:

DANGEROUS=">foo"
eval echo $DANGEROUS

Os argumentos arbitrários para echopoderiam ter feito algo mais nefasto do que criar um arquivo chamado "foo".

Celada
fonte
6
Também DANGEROUS="hello;ls":, para comandos arbitrários no lugar de ls.
Kusalananda
2
Além disso: DANGEROUS='$(ls)'(pode ser necessário mais escape).
wizzwizz4
Funcionaria eval echo '"'"$DANGEROUS"'"'? Parece que em goo.gl/L2pPQP
Ismael Miguel
@IsmaelMiguel Isso não funciona nos exemplos da wizzwizz, Cyker ou sorontar, ou para qualquer coisa com aspas duplas na string (por exemplo DANGEROUS='">foo"').
Gordon Davisson
Droga. Eu achei algo que ajudou um pouco
Ismael Miguel
26

@Celada forneceu uma excelente resposta. Para demonstrar evalé realmente ruim, aqui está algo mais nefasto do que criar um arquivo chamado "foo" :

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

E é claro que pode haver algo mais nefasto do que algo mais nefasto do que criar um arquivo chamado "foo" .

Cyker
fonte
8
+1 por demonstrar que citar a variável como em "$THIS"vez de apenas tê-la como $THISisso nem ajuda!
Celada
Enviar um par de aspas adicionais parece ajudar. Algo como eval echo '"'"$DANGEROUS"'"'. Tente em goo.gl/L2pPQP
Ismael Miguel
Na verdade, seu exemplo não é mais nefasto do que >foo, porque "criar um arquivo chamado 'foo'" não é necessariamente tudo o que >foofaz. A única diferença real que seu exemplo tem é que ele não deixa um arquivo vazio para trás. O conteúdo ainda se foi.
precisa saber é o seguinte
12

Não, nem sempre é seguro. Uma avaliação pode executar qualquer comando.

Um comando seguro, como este (a data não é executada, pois está entre aspas simples):

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

Torna-se perigoso se usado com eval:

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

Claro, a data pode ser qualquer comando.

Uma maneira de melhorar isso é citar adicionalmente os argumentos para avaliar:

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

Mas geralmente é difícil citar corretamente duas vezes uma expressão.

E torna-se impossível controlar a citação correta se a expressão puder ser definida por um invasor externo, como:

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

Embora seja verdade que evalsempre precisa ser abordado com cautela, a eval echoconstrução nem sempre é inútil e pode ser usada com segurança. Recentemente, eu precisava dele para obter várias expansões de chaves avaliadas na ordem em que eu precisava.

bash faz várias expansões de braçadeira da esquerda para a direita,

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

expande para

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

mas eu precisava da segunda expansão de braçadeira feita primeiro, produzindo

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

O melhor que eu pude fazer para isso foi

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

Isso funciona porque as aspas simples protegem o primeiro conjunto de chaves da expansão durante a análise da evallinha de comando, deixando-as serem expandidas pelo subshell invocado por eval.

Pode haver algum esquema astuto envolvendo expansões de chaves aninhadas que permita que isso aconteça em uma única etapa, mas se houver, sou velho e estúpido demais para vê-lo. Também existem outras conchas bashque permitem maneiras mais organizadas de alcançar esse tipo de coisa. Mas, em qualquer caso, esse uso de evalé seguro porque seus argumentos são todos cadeias fixas que não contêm expansões de parâmetro.

flabdablet
fonte
Você não precisa de eco e substituição de comando aqui (que também depende de $ IFS). Você poderia fazereval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
Isso funciona também, mas faz com que o processo de sub-shell gerado por eval permaneça até o processo xargs terminar; a versão eval echo faz com que esse subshell desapareça antes mesmo que o xargs seja iniciado. Esta é, provavelmente, só importante para os outros que são tão anal como me sobre o que aparece na vista de árvore htop e definir registros -x embora :-)
flabdablet