限制 CL API、禁用双冒号访问、CL 中的权限访问管理器的可能方法

问题描述 投票:0回答:1

我需要隐藏危险的功能,例如, cl:开放从互联网下载的第三方代码。

所以我可以这样做:

(package :dangerous (:use :cl))
(import 'cl:open :dangerous)
(import 'cl:export :dangerous)
...

(unexport 'open :cl)
(unexport 'export :cl)
...

; instead of cl:export which hided implement own export fn and then import it to untrusted package

(load "untrusted-lib.lisp")

据我了解,不受信任的代码根本无法调用 cl:open,除非使用 cl::open,对吗? 可以通过其他方式调用 cl:open 吗?

乍一看,如果禁用双冒号访问,CL 有可能限制对 API 的访问。 理论上可以创建安全管理器(权限访问管理器) 是否可以禁用 SBCL 和其他 CL 编译器的“::”调用?

security common-lisp
1个回答
0
投票

您给出的代码非常不符合要求(您修改了 CL 包),并且即使符合要求也无法解决问题。

这是击败它的简单方法:

(setf (fdefinition 'my-open)
      (do-symbols (s :cl)
        (when (string= (symbol-name s) "OPEN")
          (return (fdefinition s)))))

这是另一个(这个更好,但我后来想到的):

(setf (fdefinition 'my-open)
     (fdefinition (find-symbol "OPEN" :cl)))

还会有更多。

因此,这样的方法确实是解决问题的无望方法,即使 Common Lisp 是合法的,但事实并非如此。

CL 并不是一种在设计时就考虑到这种限制的语言,因此好的解决方案是介于困难和不可能之间的。

也许一种方法如下。

  1. 根据从 CL 包导出的符号和其他功能来确定该语言的安全子集是什么。 几乎可以肯定,从一个非常小的子集开始工作,而不是找出需要从语言中排除的内容,因为到处都有陷阱(例如,您必须禁止任何操纵包系统的东西,或者任何允许字符串到符号的查找,以及许多其他事情)。
  2. 设计一个包,仅重新导出 CL 中位于此安全子集中的名称。
  3. 设计一个安全的阅读器。 这至少应该防止读取时评估,以及可能的其他事情。 请记住,CL:READ 的设计可能没有考虑到安全性。
  4. 拥有仅使用上述安全包的用户包。 您可能想要经常删除此包的所有内部符号,或者只是经常删除并重新创建该包。
  5. 编写一个函数,一旦读取了表单,它将遍历它,检查其中的所有符号是否在您的好列表中或在用户包的内部。 确保这个步行者在所有情况下都终止(注意循环),并走进它需要的所有结构。
  6. 现在你的流程就差不多了:
    1. 使用安全阅读器阅读表格并正确设置包裹;
    2. 检查此表格不包含与您的学步车有关的任何不良内容;
    3. 评估表格。
  7. ...利润。

您可能还希望有一个“清理”阶段:在每次评估之前隐藏系统的包状态(这很费力但可能),然后在评估之后检查您没有预料到的任何变化。 您可能还需要某种可以围绕评估的超时机制。

并不声称这就足够了。 我并不认为这在 CL 中是完全“可能”的。 但类似这样的东西可能会有所帮助,如果是的话。 我碰巧知道 conduit packages

最初是作为系统的一部分编写的,该系统试图做到这一点。 因此,这是定义一个仅重新导出部分内容的包的好方法,例如

CL:

(define-conduit-package :just-conses
  (:extends/including :cl
   #:cons #:car #:cdr #:nil ...))


© www.soinside.com 2019 - 2024. All rights reserved.