假设我有一个Perl脚本,其中包含一个替换命令,该命令将替换字符串作为位置参数并使用/e
修饰符:
perl -pe 's/abc/$ARGV[0]/ge;'
此方法是否存在任何安全问题?我的意思是可以给出这样的位置参数值,使perl执行不需要的功能吗?我的意思是类似的:perl -pe 's/abc//;unlink ("/tmp/file");'
。
答案 0 :(得分:6)
perl -pe 's/abc/$ARGV[0]/ge'
此方法是否存在任何安全问题?我的意思是可以给出这样的位置参数值,使perl执行不需要的函数吗?
在
perldoc perlop
在该部分
Regexp Quote-Like Operators
它解释了
eval
评估结果。但这并非完全正确。在这两种情况下,“右侧” - 替换 - 被评估为好像是do
块†。在第一种情况下,结果提供替换字符串,而在第二种情况下,结果传递给eval
,的结果提供替换字符串。没有任何区别,替换首先被评估为“表达式”,而第二个被评估为“字符串”。
/e
和/ee
都允许任何有效的Perl代码序列,包括循环,条件和多个语句,并且不限于单个表达式
孤立$ARGV[0]
从来没有任何问题。只有当您执行它们时,受污染的字符串才会变得危险,无论是使用eval
还是使用system
,还是使用qx//
,/e
或反引号作为shell代码。因此,使用单个perl -pe 's/abc/qx{$ARGV[0]}/eg'
修饰符进行替换的替换部分很好
但如果您在替换中使用其他内容,例如
perl -pe 's/abc/unlink glob "*.*"/eg'
然后该参数将作为shell命令执行,因此显然不安全。但当时也不是
/ee
所以你必须明白它
什么是危险的 是double-e修饰符do
,它将替换视为Perl eval
块,然后执行{ {1}}结果。像
s/abc/$ARGV[0]/eeg
非常不安全,因为您可以像这样运行代码
perl -pe 's/abc/$ARGV[0]/eeg' 'unlink glob *.*'
只需一个/e
,这只会将abc
替换为字符串
unlink glob *.*
在$ARGV[0]
。但是使用/ee
,字符串将传递给eval
并删除所有文件!
记住这一点:
/ e - 替换是表达式(do
块)
/ ee - 替换是表达式(do
阻止),结果传递给 eval
†
这就是为什么我选择使用大括号来分隔使用/e
模式之一的替换。随着
s{abc}{ $ARGV[0] }ge
替换看起来更像是代码块,而不是我使用了常用的斜杠
答案 1 :(得分:2)
与/ee
不同,/e
没有固有的风险,因为它没有调用Perl解析器。它只会导致评估源文件中的代码,就像map BLOCK LIST
和for (LIST) BLOCK
评估其BLOCK
的方式一样。
请注意
s{$foo}{$bar}g
只是
的简称s{$foo}{ qq{$bar} }eg
所以,如果您对
感到满意perl -pe's/abc/$ARGV[0]/g'
然后你就可以了
perl -pe's/abc/"$ARGV[0]"/eg'
和几乎相同的
perl -pe's/abc/$ARGV[0]/eg'