假设我有一个Perl脚本,其中包含一个替换命令,它将替换字符串作为位置参数并使用/e
修饰符:
perl -pe 's/abc/$ARGV[0]/ge;'
Run Code Online (Sandbox Code Playgroud)
这种方法是否存在安全问题?我的意思是可以给出这样的位置参数值,使perl执行不需要的功能吗?我的意思是类似的:perl -pe 's/abc//;unlink ("/tmp/file");'
.
perl -pe 's/abc/$ARGV[0]/ge'
Run Code Online (Sandbox Code Playgroud)
这种方法是否存在安全问题?我的意思是可以给出这样的位置参数值,使perl执行不需要的功能吗?
在
perldoc perlop
一节中的
正则表达式报价样运营商
它解释
eval
结果.但这并非完全正确.在这两种情况下,"右侧" - 替换 - 被评估为好像是do
块†.在第一种情况下,结果提供了替换字符串,而在第二个的结果被传递到eval
和的结果的是提供替换字符串.没有任何区别,其中替换被首先评估为"表达"并且在第二个中被评估为"字符串".
二者/e
并/ee
允许任何有效的Perl代码序列,包括循环,条件,和多个语句,并且不限于单个表达
$ARGV[0]
隔离从来没有任何问题.受污染的字符串成为唯一的,如果你危险的执行它们,要么像Perl,使用eval
,或作为shell代码使用system
,qx//
或反引号.因此,在使用单个/e
修饰符进行替换的替换部分中,这很好
但是,如果您在替换中使用其他东西,例如
perl -pe 's/abc/qx{$ARGV[0]}/eg'
Run Code Online (Sandbox Code Playgroud)
然后该参数将作为shell命令执行,因此显然不安全.但当时也不是
perl -pe 's/abc/unlink glob "*.*"/eg'
Run Code Online (Sandbox Code Playgroud)
所以你必须明白它
什么是危险的是double-e修饰符/ee
,它将替换作为Perldo
块处理,然后eval
对结果进行处理.所以像
s/abc/$ARGV[0]/eeg
Run Code Online (Sandbox Code Playgroud)
是非常不安全的,因为你可以像这样运行你的代码
perl -pe 's/abc/$ARGV[0]/eeg' 'unlink glob *.*'
Run Code Online (Sandbox Code Playgroud)
只是一个单一的/e
,这将只替换abc
与字符串
unlink glob *.*
在$ARGV[0]
.但是使用/ee
,传递的字符串eval
将删除所有文件!
记住这一点:
/ e - 替换是表达式(do
块)
/ ee - replacement是一个表达式(一个do
块),结果传递给eval
†
这就是为什么我选择使用大括号来界定使用其中一种/e
模式的替换.随着
s{abc}{ $ARGV[0] }ge
该更换看起来更像代码块,这是比我曾用通常的斜杠