使用`eval echo'总是安全吗?


20

eval通常不建议使用,因为它允许执行任意代码。但是,如果使用eval echo,则看起来字符串的其余部分将成为的参数,echo因此应该是安全的。我对此是否正确?


1
并不总是安全的,你可以-FR *换一个叉炸弹或讨厌的RM
μολὼν.λαβέ

也许这只是一个思想实验,但如果您实际上是想这样做,以将多个参数传递给like -n,则可以使用未加引号的变量来实现,例如echo $argumentsif或if $arguments是array echo "${arguments[@]}"。使用eval echo是没有意义的,即使它安全的。
JoL

Answers:


40

反例:

DANGEROUS=">foo"
eval echo $DANGEROUS

echo与创建名为“ foo”的文件相比,使用任意参数可以做的更有害。


6
另外:DANGEROUS="hello;ls",用于代替的任意命令ls
库萨兰达

2
另外:(DANGEROUS='$(ls)'可能需要更多转义)。
wizzwizz4 2016年

eval echo '"'"$DANGEROUS"'"'工作吗?它似乎在goo.gl/L2pPQP上
Ismael Miguel

@IsmaelMiguel不适用于wizzwizz,Cyker或sorontar的示例,或字符串中带有双引号的任何内容(例如DANGEROUS='">foo"')。
戈登·戴维森

真是 我虽然发现有帮助的地方
Ismael Miguel

26

@Celada提供了一个很好的答案。演示eval确实很邪恶,这比创建一个名为“ foo”的文件更有害:

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

当然,可能比创建一个名为“ foo”的文件更有害


8
+1表示引用变量"$THIS"而不是仅仅引用变量$THIS甚至没有帮助!
塞拉达

发送一对附加的报价似乎有所帮助。有点像eval echo '"'"$DANGEROUS"'"'。在goo.gl/L2pPQP
Ismael Miguel

实际上,您的示例并没有比邪恶>foo,因为“创建一个名为'foo'的文件”并不一定是全部>foo。您的示例唯一的真正区别是它不会留下任何空文件。内容仍然不见了。
flarn2006 '18

12

不,它并不总是安全的。评估可以执行任何命令。

像这样的安全命令(日期不执行,因为它在单引号内):

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

与eval一起使用时会变得危险:

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

当然,日期可以是任何命令。

改善此问题的一种方法是另外引用eval的参数:

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

但是通常很难正确引用一个表达式两次。

如果表达式可由外部攻击者设置,则无法控制正确的报价,例如:

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

1

尽管确实需要eval始终谨慎行事,但这种eval echo结构并非总是毫无意义,可以安全使用。最近,我需要它来按执行顺序对多个支撑扩展进行评估。

bash 从左到右执行多个括号扩展,所以

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

扩展到

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

但是我需要先完成第二个支撑扩展,

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

我能想到的最好的办法是

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

之所以可行,是因为单引号可以保护第一组大括号免于在eval命令行解析期间进行扩展,而使它们可以由调用的子shell进行扩展eval

可能存在一些涉及嵌套括号扩展的狡猾方案,使它可以一步完成,但是如果有的话,我太老太笨了,看不到它。除此以外bash,还有其他外壳允许采用更简洁的方式来实现这种目标。但是无论如何,这种使用eval是安全的,因为它的参数都是固定的字符串,不包含任何参数扩展。


您在这里不需要echo和命令替换(它也依赖于$ IFS)。你可以这样做eval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
斯特凡Chazelas

那也可行,但是它使子壳进程由eval生成,直到xargs进程完成为止。eval echo版本使该子外壳在xargs甚至启动之前就消失了。这可能仅对像我这样肛门的其他人很重要,尽管它们显示在htop树视图中并设置了-x日志:-)
flabdablet
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.