Perl通过正则表达式污染

时间:2013-12-03 16:01:21

标签: regex perl security taint

短版

在下面的代码中,$1被污染了,我不明白为什么。

长版

我在使用perl v5.14.2且启用了-T污点检查模式的系统上运行Foswiki。 调试该设置的问题,我设法构建以下SSCCE。 (请注意,我编辑了这篇文章,第一个版本更长,更复杂,评论仍然提到了这一点。)

#!/usr/bin/perl -T
use strict;
use warnings;
use locale;
use Scalar::Util qw(tainted);
my $var = "foo.bar_baz";
$var =~ m/^(.*)[._](.*?)$/;
print(tainted($1) ? "tainted\n" : "untainted\n");

虽然输入字符串$var未受污染且正则表达式已修复,但生成的捕获组$1仍然受到污染。我觉得这很奇怪。

perlsec manual有关于污点和正则表达式的说法:

  

通过将它们用作哈希中的键,可能无法使用值;否则   绕过污点机制的唯一方法是参考   正则表达式匹配的子模式。 Perl假定如果   你使用$1$2等引用一个子串,你知道你是什么   你写这个模式的时候正在做。

我会想象即使输入被污染,输出仍然没有污染。要观察来自无污染输入的反向,污染输出,感觉就像perl中的一个奇怪的错误。但如果一个人读取更多的perlsec,它也会指向the SECURITY section of perllocale的用户。我们读到:

  

当使用locale生效时,Perl使用污染机制(参见   perlsec)标记与语言环境相关的字符串结果,以及   这可能是不值得信任的。以下是摘要   可能受到影响的操作员和功能的污点行为   语言环境:

     
      
  • 比较运算符(ltlegegtcmp)[...]

  •   
  • 案例映射插值(\l\L\u\U)[...]

  •   
  • 匹配运算符(m//):

         

    标量真/假结果永远不会被污染。

         

    子模式,作为列表上下文结果或$1传递   如果使用区域设置(但不是use locale ':not_characters')生效,并且子模式是常规的,则会受到污染   表达式包含\w(以匹配字母数字字符),\W   (非字母数字字符),\s(空格字符)或\S   (非空白字符)。匹配模式变量$&$` (赛前),$'(赛后)和$+(最后一场比赛)也是   如果使用区域设置生效且正则表达式包含,则会受到污染   \w\W\s\S

  •   
  • 替换运算符(s///)[...]

  •   
     

[⋮]

这看起来应该是一个详尽的清单。我不明白它是如何应用的:我的正则表达式不使用\w\W\s\S中的任何一个,因此它不应该依赖于语言环境。

有人可以解释为什么这段代码会污染变种$1

1 个答案:

答案 0 :(得分:0)

目前问题中引用的文档与perl 5.18.1的实际实现之间存在差异。问题是字符类。该文档提到\w\s\W\S听起来像一个详尽的列表,而实现几乎每次使用[…]都会受到影响。

正确的解决方案可能介于两者之间:像[[:word:]]这样的字符类应该受到污染,因为它取决于区域设置。我的固定清单不应该。像[a-z]这样的字符范围取决于整理,所以在我个人看来,它们也应该受到污染。 \d取决于区域设置对数字的考虑,因此即使它既不是目前提到的转义序列也不是括号内的类,它也应该会污染。

所以在我看来,文档和实现都需要修复。 Perl开发人员正在研究这个问题。有关进度信息,请查看我提交的the perl bug report

对于固定的字符列表,一个可行的解决方法似乎是作为分离的公式,即(?:\.|_)而不是[._]。它更详细,但即使使用当前(在我看来有错误)perl版本也应该工作。