Answers:
反例:
DANGEROUS=">foo"
eval echo $DANGEROUS
echo
与创建名为“ foo”的文件相比,使用任意参数可以做的更有害。
DANGEROUS="hello;ls"
,用于代替的任意命令ls
。
DANGEROUS='$(ls)'
可能需要更多转义)。
eval echo '"'"$DANGEROUS"'"'
工作吗?它似乎在goo.gl/L2pPQP上
DANGEROUS='">foo"'
)。
@Celada提供了一个很好的答案。演示eval
确实很邪恶,这比创建一个名为“ foo”的文件更有害:
DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"
当然,可能比创建一个名为“ foo”的文件更有害。
"$THIS"
而不是仅仅引用变量$THIS
甚至没有帮助!
eval echo '"'"$DANGEROUS"'"'
。在goo.gl/L2pPQP
>foo
,因为“创建一个名为'foo'的文件”并不一定是全部>foo
。您的示例唯一的真正区别是它不会留下任何空文件。内容仍然不见了。
不,它并不总是安全的。评估可以执行任何命令。
像这样的安全命令(日期不执行,因为它在单引号内):
$ 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!
尽管确实需要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
是安全的,因为它的参数都是固定的字符串,不包含任何参数扩展。
eval xargs -I_ cat _/'{11..15}'/{8..5}.jpg