【问题标题】:Lisp data security/validationLisp 数据安全/验证
【发布时间】:2010-06-08 18:34:15
【问题描述】:

在这一点上,这对我来说实际上只是一个概念性问题。

在 Lisp 中,程序是数据,数据是程序。 REPL 正是这样做的 - 读取然后评估。

那么如何以一种安全的方式从用户那里获取输入呢?显然这是可能的 - 我的意思是 viaweb - 现在 Yahoo!Stores 非常安全,那么它是如何实现的呢?

【问题讨论】:

    标签: security validation lisp


    【解决方案1】:

    REPL 代表读取评估打印循环。

    (loop (print (eval (read))))
    

    以上只是概念性的,真正的 REPL 代码要复杂得多(包括错误处理、调试等)。

    您可以在 Lisp 中读取各种数据而无需对其进行评估。评估是一个单独的步骤 - 独立于读取数据。

    Lisp 中有各种各样的 IO 函数。提供的函数中最复杂的通常是 READ,它读取 s 表达式。 Common Lisp 中有一个选项允许在 READ 期间进行评估,但在读取数据时可以并且应该将其关闭。

    因此,Lisp 中的数据不一定是程序,即使数据是程序,Lisp 也可以将程序作为数据读取 - 无需评估。 REPL 只能由开发人员使用,不应暴露给任意用户。为了从用户那里获取数据,可以使用普通的 IO 函数,包括像 READ 这样的函数,它可以读取 S 表达式,但不计算它们。

    以下是一些不应该做的事情:

    • 使用 READ 读取任意数据。 READ 示例允许人们读取非常大的数据 - 没有限制。

    • 在读取期间进行评估(“读取评估”)。这应该被关闭。

    • 从 I/O 读取符号并调用其符号函数

    • 当您的函数需要纯列表时,使用 READ 读取循环数据结构。遍历循环列表可以让您的程序忙碌一段时间。

    • 在读取数据时不处理语法错误。

    【讨论】:

      【解决方案2】:

      您按照其他人的方式进行操作。您从流中读取一串数据,解析它以获取命令和参数,验证命令和参数,并解释命令和参数。

      这里没有魔法。

      简单地说,您不应该做的就是不将您的 Lisp 侦听器暴露给未经验证、不安全的数据源。

      如前所述,REPL 是读取 - 评估 - 打印。 @The Rook 专注于 eval (有理由),但不打折阅读。 READ 是 Common Lisp 中一个非常强大的命令。阅读器可以在您甚至 GET 到“eval”之前自行评估代码。

      不要将 READ 暴露给您不信任的任何事物。

      通过足够的工作,您可以制作一个自定义包,限制该包可用的功能范围等。但是,我认为这比简单地自己编写一个简单的命令解析器而不用担心一些副作用我错过了。

      【讨论】:

      • 这正是我担心的地方——读者可以评估代码。是否有某种相当于 Python 2.6 raw_input() 的类型?
      【解决方案3】:
      1. 创建您自己的 readtable 并填充必要的钩子:SET-MACRO-CHARACTER、SET-DISPATCH-MACRO-CHARACTER 等。
      2. READTABLE 绑定到您自己的 readtable。
      3. READ-EVAL 绑定到 nil 以防止 #。 (如果步骤 1 正确,则可能不需要)
      4. 阅读

      可能是别的东西。

      在阅读时在临时包中插入符号也有一个技巧。

      如果数据不是 LL(1)-ish,只需编写普通解析器。

      【讨论】:

        【解决方案4】:

        这是一个致命的问题,当我阅读 Lisp 时,我也有同样的想法。虽然我在 LISP 中没有做任何有意义的事情,所以我的回答非常有限。

        我可以告诉你的是eval()is nasty。有句话我喜欢“如果 eval 是答案,那么你问错了问题”。 - 未知。

        如果攻击者可以控制然后评估的数据,那么您就有一个非常严重的远程代码执行漏洞。这可以缓解,我将向您展示一个 PHP 示例,因为这是我所知道的:

        $id=addslashes($_GET['id']);
        eval('$test="$id";');
        

        如果您没有添加斜杠,那么攻击者可以通过这样做来远程执行代码:

        http://localhost?evil_eval.php?id="; phpinfo();/*
        

        但是添加斜线会将" 变成\",从而阻止攻击者“破解”“数据”并能够执行代码。这与sql注入非常相似。

        【讨论】:

        • +1 表示报价。这可能适用于大多数任何语言。当然,任何时候我使用 php,输入总是包装在一个 htmlspecialchars()
        【解决方案5】:

        我发现这个问题没有争议。除非您明确要求,否则 eval 不会评估您的输入。 我的意思是您的输入不会被视为 LISP 代码,而是被视为字符串。

        不是因为你的语言有像 eval 这样强大的概念,它不“安全”。

        我认为混淆来自 SQL,您实际上将输入视为 SQL 的 [部分]。

        (query (concatenate 'string "SELECT * FROM foo WHERE id = " input-id))
        

        这里的 input-id 正在由 SQL 引擎评估。 这是因为您没有编写 SQL 或其他什么的好方法,但关键是您的输入成为正在评估的内容的一部分。

        所以 eval 不会给你带来不安全感,除非你闭着眼睛使用它。

        编辑忘了说这适用于任何语言。

        【讨论】:

          猜你喜欢
          • 2021-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-10
          • 2017-04-28
          • 2019-02-07
          • 2019-04-16
          • 1970-01-01
          相关资源
          最近更新 更多