【问题标题】:Perl tainting via regular expression通过正则表达式进行 Perl 污染
【发布时间】:2013-12-06 09:20:29
【问题描述】:

短版

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

加长版

我在启用了-T 污点检查模式的 perl v5.14.2 系统上运行 Foswiki。 调试该设置的问题后,我设法构建了以下 SSCCE。 (注意我编辑了这个帖子,第一个版本更长更复杂,cmets仍然参考。)

#!/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。我们读到:

当使用区域设置生效时,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

【问题讨论】:

  • 我认为如果你删除(奇怪的写作方式)use locale;,它不会被污染?使用perlbug 工具将其发送到p5p 不会有什么坏处。如果不是文档中的错误,Perl 中似乎存在错误。
  • Scalar::Util qw(tainted) 有什么问题?
  • @mpapec:Scalar::Util::tainted 没有问题,它产生相同的结果。我只是在此处粘贴了 Foswiki 使用的代码,因为它可能会稍微减少该代码的依赖关系。我不知道是否每个人都有可用的Scalar::Util,文档建议使用 CPAN。
  • Scalar::Util 自 5.8.0 以来一直是核心模块,十多年前。

标签: regex perl security taint


【解决方案1】:

目前问题中引用的文档与 perl 5.18.1 的实际实现之间存在差异。问题是字符类。文档中提到了\w,\s,\W,\S,这听起来像是一个详尽的列表,而实现几乎涉及[…]的所有使用。

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

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

对于固定的字符列表,一种可行的解决方法似乎是将公式作为析取,即(?:\.|_) 而不是[._]。它更冗长,但即使在当前(我认为有缺陷的)perl 版本中也应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    相关资源
    最近更新 更多