Regex 通过正则表达式进行Perl污染 短版

Regex 通过正则表达式进行Perl污染 短版,regex,perl,security,taint,Regex,Perl,Security,Taint,在下面的代码中,$1被污染了,我不明白为什么 长版本 我在一个启用了污染检查模式的PerlV5.14.2系统上运行。 通过调试该设置中的一个问题,我成功地构建了以下SSCCE。(请注意,我编辑了这篇文章,第一个版本更长、更复杂,评论中仍然提到这一点。) 尽管输入字符串$var未被污染,并且正则表达式是固定的,但生成的捕获组$1受到污染。我觉得很奇怪 对于污点和正则表达式,有这样的说法: 通过将值用作散列中的键,可以不受污染;否则 绕过污染机制的唯一方法是引用 正则表达式匹配的子模式。Perl假定

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

长版本 我在一个启用了污染检查模式的PerlV5.14.2系统上运行。 通过调试该设置中的一个问题,我成功地构建了以下SSCCE。(请注意,我编辑了这篇文章,第一个版本更长、更复杂,评论中仍然提到这一点。)

尽管输入字符串
$var
未被污染,并且正则表达式是固定的,但生成的捕获组
$1
受到污染。我觉得很奇怪

对于污点和正则表达式,有这样的说法:

通过将值用作散列中的键,可以不受污染;否则 绕过污染机制的唯一方法是引用 正则表达式匹配的子模式。Perl假定如果 您使用
$1
$2
等引用子字符串,您知道您要引用的内容 你写模式的时候我们在做什么

我可以想象,即使输入被污染了,输出也不会被污染。观察未受污染输入的反向污染输出,感觉就像perl中的一个奇怪的bug。但如果你多读一些perlsec,它也会指向用户。我们在那里读到:

当use locale生效时,Perl使用污染机制(请参阅 perlsec)标记与区域设置相关的字符串结果,以及 结果可能是不可信的。以下是本报告的摘要 可能受影响的运算符和函数的污染行为 区域设置:

  • 比较运算符(
    lt
    le
    ge
    gt
    cmp
    )[…]

  • 案例映射插值(使用
    \l
    \l
    \u
    \u
    )[…]

  • 匹配运算符(
    m/
    ):

    标量真/假结果从不受污染

    子模式,作为列表上下文结果或作为
    $1
    如果使用区域设置(但不是
    使用区域设置),则会污染等
    “:not_characters”
    )有效,并且子模式为常规模式 表达式包含
    \w
    (用于匹配字母数字字符),
    \w
    (非字母数字字符)、
    \s
    (空白字符)或
    \s
    (非空白字符)。匹配的模式变量,
    $&
    $`
    
    (预匹配)、
    $”
    (后匹配)和
    $+
    (最后一次匹配)也都是 如果使用区域设置有效且正则表达式包含
    \w
    \w
    \s
    \s

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

[⋮]

这看起来应该是一个详尽的列表。我不知道如何应用它:我的正则表达式没有使用任何
\w
\w
\s
\s
,因此它不应该依赖于语言环境


有人能解释一下为什么这段代码污染了varibale
$1

问题中引用的文档与perl 5.18.1的实际实现之间存在差异。问题是字符类。文档提到了
\w
\s
\w
\s
,在什么方面听起来像是一个详尽的列表,而几乎每次使用
[…]
时,实现都会受到污染

正确的解决方案可能介于两者之间:像
[[:word:]
这样的字符类应该受到污染,因为它取决于区域设置。我的固定列表不应该受到污染。像
[a-z]这样的字符范围
取决于排序规则,因此我个人认为它们也应该被污染。
\d
取决于区域设置对数字的看法,因此它也应该被污染,即使它既不是目前提到的转义序列,也不是括号中的类

因此,在我看来,文档和实现都需要修复。Perl开发人员正在处理这个问题。有关进度信息,请查看我提交的文档


对于一个固定的字符列表,一个可行的解决办法似乎是将其表述为析取,即
(?:\.\124;
而不是
[.\u]
。它更为详细,但即使在当前(我认为有缺陷的)perl版本中也应该可以使用。

我认为如果删除(奇怪的编写方式),它不会受到污染
use locale;
?使用
perlbug
工具将此信息发送到
p5p
不会有什么坏处。如果不是文档中的错误,Perl中似乎存在错误。
Scalar::Util qw(受污染)有什么问题
?@mpapec:Scalar::Util::tainted没有什么问题,它会产生相同的结果。我只是将Foswiki使用的代码粘贴在这里,因为它可能会减少代码的依赖性。我不知道是否每个人都有可用的
Scalar::Util
,文档建议使用CPAN。Scalar::Util自5.8.0,十多年前。@ikegami:在
#!/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");