通常不鼓励使用它eval
,因为它允许执行任意代码。但是,如果我们使用eval echo
,那么看起来字符串的其余部分将成为 的参数,echo
因此它应该是安全的。我的说法正确吗?
答案1
反例:
DANGEROUS=">foo"
eval echo $DANGEROUS
的任意参数echo
可能会做出比创建名为“foo”的文件更邪恶的事情。
答案2
@Celada 提供了一个很好的答案。示威eval
真的很邪恶,这里是比创建名为“foo”的文件更邪恶的东西:
DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"
当然也可以有比创建名为“foo”的文件更邪恶的事情。
答案3
不,是不是永远安全。 eval 可以执行任何命令。
一个安全的命令,如下所示(日期不会被执行,因为它在单引号内):
$ 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!
答案4
虽然确实总是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
。
可能有一些涉及嵌套大括号扩展的狡猾方案,可以让这种情况一步发生,但如果有的话,我太老了,太愚蠢了,看不到它。除此之外,还有其他 shellbash
允许以更简洁的方式来实现这种事情。但无论如何,这种使用eval
是安全的,因为它的参数都是不包含参数扩展的固定字符串。