【问题标题】:Is the Perl Parser safe to parse arbitrary code?Perl Parser 可以安全地解析任意代码吗?
【发布时间】:2018-09-30 15:15:45
【问题描述】:

我很难找到一个权威的答案。 Perl 5 Parser 是否可以安全地解析任意代码?忽略运行或执行代码的含义,解析器本身是否安全?

解析器中允许执行任意代码的漏洞将被视为安全漏洞还是错误?

似乎有些票从安全列表中被拒绝,并在特定于解析器的错误上被推送到一般,

例如,a "Keeper of the Pumpkin" Tony Cook says,

我认为总的来说,我们认为这些问题不是安全问题,毕竟,如果攻击者可以向解析器提供代码,那么你已经很容易受到攻击。

具体来说,我试图澄清这两种威胁模型,

  • Safe 假设 Perl 能够正确生成黑名单/白名单操作码树
  • Perl (p5p) 假设所有解析都是使用任意代码执行的全部功能完成的,并且如果提供了恶意代码,则您“已经很容易受到攻击”

问题

知道你为什么问会很有趣。这方面的信息可以为您提供更好的答案。

如果 perl 解析器无法安全地解析代码,那么我相信没有任何东西可以保护任意 Perl。所以 Safe.pm 和 OpCode.pm 的全部目的是没有意义的,因为你不能安全地生成一个操作码树来修剪(黑名单操作码)。如果是这样,那么文档中的任何地方都不清楚,并且对这种事情保密是一个非常糟糕的主意。命名删除和开放软件以供利用是不安全的。

【问题讨论】:

    标签: security parsing perl


    【解决方案1】:

    Perl 5 Parser 可以安全地解析任意代码吗?

    没有。

    BEGIN { print "This runs at parse time.\n" }
    

    也无法禁用此行为,因为在解析时运行的代码可能会执行解析以下代码所需的操作,例如安装源过滤器或添加关键字。

    【讨论】:

    • 但是 BEGIN 块中的任何内容都会在解析该 BEGIN 块之后发生。例如,您不能使用BEGIN 块来解决Opcode.pm,对吗?但是,该 BEGIN 块的解析是否安全,这意味着从任意源本身构造 perl optree。
    • @EvanCarroll BEGIN 块在解析周围代码期间执行。 BEGIN 块可以嵌套。为了正确解析以下代码,必须尽快执行 BEGIN 块。所以你不能认为 perl 的解析器与 perl 的解释器是分开的——两者密不可分。解析 Perl 意味着执行 Perl。因此,perl -c 是一种谎言,因为它执行 BEGIN 块。
    • 我很困惑,如果它们是密不可分的,那么 OpCode.pm 是如何工作的,以至于我无法认为它是一个独立于 BEGIN {} 解析的过程
    • @EvanCarroll 虽然解析和执行是混合在一起的,但不同的阶段仍然是有序的。您可以在解析某些代码之前应用限制。 Opcode 限制(内部为 PL_op_mask 数组)在创建 OP 后立即检查,即在解析期间和执行之前。参见 perl 解释器 op.c 中的 CHECKOP 宏。
    • 我不确定我是否理解您如何使用“不同”和“混合”:如果您有操作码,则解析完成。如果解析器不安全,你可以生成任何你想要的操作码,假设你发现了一个错误——Perl 社区不会认为它是一个“安全漏洞”,因为解析任意代码是不安全的。我不清楚这两个词之间的区别,或者BEFORE 如何说明 parsing(问题的主题)而不是 execution 的问题?
    【解决方案2】:

    您不应将不受信任的代码提供给perlPerl security model 以数据为中心(例如通过 taint 标志),而不是为代码提供沙箱。 IE。您应该能够编写安全的程序,但不一定能够安全地运行任意程序。所以如果有人能够执行代码,你应该假设他们确实能够执行任何代码。

    其中一个方面是 Perl 的多阶段执行模型。 BEGIN 块在解析后立即执行。这是正确解析后续代码所必需的。 use 语句也是 BEGIN 块。所以因为解析的时候必须要执行代码,所以认为先解析Perl代码再执行的想法是不正确的。考虑这个例子:

    say 4;
    BEGIN {
      say 2;
      BEGIN { say 1 }
      say 3;
    }
    say 5;
    

    每个 BEGIN 块在解析完成后立即执行,从而产生编号的执行顺序。重要的是,在完成整个文档的解析之前会执行一些代码。

    在解析时,perl 编译器会创建一个 optree。这个 optree 既是解析器的抽象语法树,又是 Perl 解释器的操作码。

    Perl 确实提供了通过Opcode 模块过滤操作的能力,该模块只能通过前端opsSafe 使用。这些可以设置一个掩码,该掩码控制在掩码生效时可以创建哪些操作码。因此,如果我们禁止循环操作码但解析了循环,则解析将在该点失败。重要的是,掩码不会在编译和执行之间过滤操作码(这两个阶段没有明确划分!)。相反,它会阻止这些操作码永远存在。

    这有很多重要的警告。

    • 解析容易出错。如果解析代码中存在漏洞,则可能会被特制输入利用。

    • Safe 模块尝试将允许的操作码列入白名单或黑名单。但是,不一定清楚某组允许的操作码是安全的。 Perl 在设计时并未考虑到沙盒。

      另外,很多功能不是由操作码提供的,而是由子程序提供的,这些子程序可能在操作码掩码到位之前就已经编译好了。它们的功能或实现中的漏洞可用于逃避沙箱。特别是,我希望这里可以使用许多 XS 模块,因为它们经常公开指向 Perl 代码的指针。

    如果您必须执行不受信任的 Perl 代码,最好使用操作系统级别的安全功能,可能是 Perl 安全功能的补充。我想到了 Linux 容器化技术。如果您在沙盒进程中执行任何解析 + 执行,这对于不受信任的代码可能足够安全——前提是沙盒配置正确。例如。可以构建一个 seccomp 规则链来允许/拒绝某些系统调用。 Cgroups 可以设置细粒度的资源限制。

    【讨论】:

    • 当您说“解析容易出错。如果解析代码中存在漏洞,则可能会被特制输入利用。”您使用术语“漏洞”,您能解释一下 perl 团队如何解释这个问题——这样的问题是“错误”还是“安全”问题?它还会发送哪个列表,perl 威胁模型将如何考虑这一点? cve会出去吗?这就是我真正想要的。
    • 我不能告诉你 p5p 会做什么。我认为解析器漏洞利用是严重的、安全敏感的和 CVE 值得的错误,但不是灾难性的安全问题。对于大多数应用程序,如果您可以将任意代码传递给 perl,那么您已经可以运行任意代码并且不需要此类漏洞利用。反例是评估用户输入的 setuid 脚本(天哪,为什么??)。但是由于多阶段执行模型,在开始解析不受信任的代码之前,它们必须已经实现了一些沙箱,并且会包含解析器漏洞。我不认为Safe 是一个足够的沙箱。
    • 对,但重点是威胁模型对齐。如果使用 Safe.pm 正确构建产品,缺乏操作系统级别的隔离,那么 100% 的安全相关问题都值得 CVE。从 tcook 的声明来看,我认为 p5p 和 Safe 用户之间存在威胁建模问题。 Safe 假设 Perl 能够正确生成黑名单/白名单操作码树,而 Perl 假设所有解析都使用任意代码执行的全部功能完成。
    猜你喜欢
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多