public 网络服务器可以使用 Perl 的 Marpa 解析器吗?

Is it possible to use Perl's Marpa parser for a public network server?

Perl 的文档 Marpa parser contains the following section about tainted data:

Marpa::R2 exists to allow its input to alter execution in flexible and powerful ways. Marpa should not be used with untrusted input. In Perl' s taint mode, it is a fatal error to use Marpa's SLIF interface with a tainted grammar, a tainted input string, or tainted token values.

我不确定,如果我理解这个限制的后果。我明白,语法不能被污染。但是我不明白输入一定不能被污染。对我来说,解析器的任务是验证输入。解析器必须信任它的输入对我来说听起来很不合理。

真的是这样吗?是否无法使用 Marpa 实现任何类型的 public 网络服务?

我问这个是因为参考用例之一是 Marpa HTML parser,在我看来,使用 HTML 的解析器是矛盾的,尽管大约 99 ,99% 的 HTML 可能被污染。

谁能解释一下这个矛盾?

taint mode 是一个 perl 可选设置,表示 - 将用户输入视为不受信任。它会阻止您使用任何 "tainted" 变量 - 例如在某些函数中从 STDINENV 直接 读取 的变量,因为这样做很危险。

代码注入漏洞的典型示例:

这就是 "taint mode" 所做的一切 - 它 强制执行 运行 在以危险方式使用不受信任的输入之前进行清理。

untainting is straightforward - 您需要做的就是对源数据应用正则表达式过滤器,以便排除任何 'dangerous' 元字符。 (应该注意 - perl 实际上不知道什么是 'dangerous' 什么不是 - 它假设你不是白痴,只是 'matching' 一切)

这会出错:

#!/usr/bin/env perl -T
use strict;
use warnings;

my $tainted = $ENV{'USERNAME'};
system ( "echo $tainted" );

因为我将 untrusted 变量传递给 "system" 并且它 可能 具有嵌入式代码注入。

Insecure dependency in system while running with -T switch at

(它可能还会抱怨路径不安全)

所以要去除污染,我需要消毒。合理的清理是 - 用户名只能是字母数字:

#!/usr/bin/env perl -T
use strict;
use warnings;

$ENV{'PATH'} = '/bin'; # an untainted value 

my $tainted = $ENV{'USERNAME'};
my ( $untainted ) = $tainted =~ m/(\w+)/g;
system ( "echo $untainted"); # no error now

并且因为我使用了正则表达式 - perl 假设我没有做一些愚蠢的事情(比如 (.*)),因此认为数据未受污染。

为什么这很重要?嗯,这取决于你的解析器做什么。解析器 - 就其本质而言 - 通过无效输入获得 'broken' 并不少见。例如,参见上面 - 转义一些内联 SQL 绕过验证。

在您的具体情况下:

  • 污点模式是可选的。您应该在收到不受信任的输入(例如来自潜在的恶意用户)时使用它,但它可能比您自己使用时更麻烦。

  • 过滤 HTML 以验证长度和字符集可能是明智的。例如 - 检查它是 "ascii compatible character encoding"

从根本上说,尽管我认为您对污点检查是什么想得太多了——它不是一种详尽无遗的验证方法——但它是一个安全网。它所做的只是确保在将用户输入传递给不安全的机制之前,您已完成一些 基本清理。这是为了阻止像我概述的那样的荒谬陷阱——其中大部分都可以通过简单的正则表达式捕获。

如果您意识到这个问题,并且不担心恶意用户输入,那么我认为您不必过分担心。字符白名单就足够了,然后解析掉。

Marpa其实比其他解析器更安全,因为它解析的语言正是BNF指定的语言。使用正则表达式、PEG 等,很难确定实际解析的是哪种语言。在实践中,程序员倾向于让一些测试用例工作然后放弃。

特别是,不需要的输入的解析可能是一个主要的安全问题——使用传统的解析器,您通常不知道您允许通过的所有内容。测试套件很少会检查应该是错误的输入是否实际上被接受了。 Marpa 完全 解析其规范中的语言——仅此而已。

那么为什么关于污点模式的恐吓语言呢?在最一般的情况下,Marpa 可以被视为一种编程语言,并且具有完全相同的安全问题。允许用户执行任意代码在定义上是不安全的,这正是 C、Perl、Marpa 等设计所做的。您不能为不受信任的用户提供通用语言界面。这对于 C、Python 等来说是很清楚的,但我认为有人可能会在 Marpa 的情况下忽略它。因此,恐吓语言。

恕我直言,Marpa 比竞争技术更安全。但是,在大多数情况下,这还不够安全。