当用户输入右侧时,使用e //修饰符安全地使用s ///操作符

时间:2015-03-17 18:50:33

标签: regex perl

我正在编写一个Perl脚本,用户可以在其中输入正则表达式和替换字符串。该脚本将搜索一组文件,并根据应用了用户输入的perl s///运算符应用更改。

为了使问题稍微复杂化,允许替换字符串包含反向引用以引用正则表达式中的捕获组。例如,如果正则表达式为b(.*?)a且替换字符串为a$1b,则不应按字面意义处理$1,而应将rater作为对第一组捕获的反向引用。

在此设置中,我想知道当此运算符的右侧是否可以使用ee运算符安全地使用s///修饰符(以评估用户输入中的反向引用)是由用户输入的?例如:

use strict;
use warnings;
my $str = 'abaaca';

my $replacement = 'do{ use Env qw(HOME); unlink "$HOME/important.txt" }';

$str =~ s/a(.*?)a/$replacement/gee;

会很不幸..但后来我想到了在用双引号和美元符号(后面没有数字)转义之后引用用户输入(把它放在一对双引号内),然后然后做替换:

use feature qw(say);
use strict;
use warnings;

my $str = 'abaaca';

my $replacement = shift;
$replacement =~ s/\"/\\\"/g;
$replacement =~ s/\$(?!\d)/\\\$/g;
$replacement = '"' . $replacement . '"';
$str =~ s/a(.*?)a/$replacement/gee;
say $str;

对我而言,这似乎乍一看,或者我错过了什么? 例如,如果脚本被调用test.pl并且用户将其运行为:

$ test.pl 'do{ "a$b" }'

输出只需要一个简单的字符串(并且不评估任何代码):

  

做{“a $ b”}做{“a $ b”}

所以问题是:这真的是一种安全/正确的方法吗?

1 个答案:

答案 0 :(得分:5)

问题1:

由于以下内容替换为$1,因此无法替换1后跟${1}1

$ script '${1}1'
${1}1${1}1

问题2:

$ script '\${ system "echo rm -rf /" }'
rm -rf /
Use of uninitialized value in substitution iterator at a.pl line 12.
rm -rf /
Use of uninitialized value in substitution iterator at a.pl line 12.

问题3:

$ script '$1{ system "echo rm -rf /" }'
rm -rf /
Use of uninitialized value within %1 in string at (eval 1) line 1.
rm -rf /
Use of uninitialized value within %1 in string at (eval 2) line 1.

当然,还有其他人。解决方案:

使用String::Substitution