【问题标题】:What Java classes/packages are safe to whitelist in a security sandbox?哪些 Java 类/包可以安全地列入安全沙箱中的白名单?
【发布时间】:2013-07-21 18:03:57
【问题描述】:

作为我正在开发的 Java 驱动游戏的一部分,我计划嵌入 Groovy(或可能其他一些)脚本语言,以支持较低级别的 mod 支持,并为对话和任务文件等内容在游戏中产生影响世界。但是我的目的和潜在模组作者的目的可能会有所不同,如果可能的话,我希望避免删除不危险的语言功能。

虽然我的具体需求当然会与公共规范有所不同,但我很好奇是否有任何公认的 java 包和类白名单(无论多么短),可以访问而不会对用户造成重大风险。

【问题讨论】:

  • 这段代码是在(例如您的)服务器上运行,还是在客户端机器上运行?
  • 不完全一样,但如果你还没有发现这个问题,它也可能对你有用:stackoverflow.com/questions/6210045/…
  • @AndrewThompson 代码将在客户端机器上运行,但令人担忧的是我最终希望添加多人游戏支持和托管改装服务器的能力。在这种情况下,我正在研究允许此类(第 3 方)改装服务器直接向连接客户端提供所需的改装文件(可能包含脚本)的可行性。这当然需要成为一个“选择加入”的过程,但这同样是一个安全问题。见here
  • "..以及托管改装服务器的能力。" 然后您甚至需要考虑像while(true); 这样简单的事情 - 这会消耗大量 CPU 周期..
  • @AndrewThompson 如果我托管的服务器正在执行用户提交的代码,这听起来更像是一个需要担心的问题。正在发生的事情是运行我的游戏的客户端将执行由我无法控制的服务器提供的代码。但是,我不认为只会导致减速的模组是安全风险,因为用户可以简单地结束程序,在下次启动时删除模组,然后继续前进。

标签: java security scripting whitelist


【解决方案1】:

不过,我很好奇是否有任何公认的 Java 包和类的白名单(无论多么短),这些包和类可以在不给用户带来重大风险的情况下访问。

是的,有白名单,但我不知道它们是如何“普遍同意”的。社区共识是审查白名单的一种方式,但您也可以查看名单创建者的经验,看看他们的流程是否有意义。


Joe-E 项目提出了对 Java 的“驯服”,其中一个部分是按类/方法/字段列出核心库的白名单。例如,对于StringBuilderStringBuilder.safej 表示

# Manually verified.
class("java.lang.StringBuilder",
  static(constructor("StringBuilder()"),
    constructor("StringBuilder(CharSequence)"),
...
    method(suppress, "insert(int, Object)", comment("calls toString on arbitrary object")),

Runtime.safej

# auto-generated safej: default deny everything
class("java.lang.Runtime",
  static(method(suppress, "getRuntime()", comment("default deny")),
    method(suppress, "runFinalizersOnExit(boolean)", comment("default deny"))),
    ...

要了解驯服,请参阅Joe-E paper,它说:

4.2.1 驯服 Java 类库

Java 库定义了许多静态方法 对外界的影响,以及许多构造函数 创建允许类似效果的对象。这是 Java 中环境权限的主要来源。例如,文件 有一个构造函数,它将接受一个字符串并返回一个对象 表示具有该名称的文件。结果对象 可用于读取、写入或删除命名文件。 Java 安全管理器没有明确的访问控制或 操作系统,这允许任何 Java 代码完全控制文件系统。在 Joe-E 中,我们希望确保 如果文件的功能,代码只能访问文件 (或超级目录)在该代码的动态范围内。

因此,我们绝不能允许上述文件 Joe-E 全局范围内的构造函数。 我们定义了 Java 库的一个子集,其中仅包含 那些兼容的构造函数、方法和字段 原则是所有特权都必须通过 能力。我们称这种活动为驯服,因为它变成了一种 不守规矩的类库变成一个能力安全的子集。 JoeE 验证器允许 Joe-E 程序只提及类, 这个驯服的子集中的构造函数、方法和字段。如果 源代码提到了这个子集之外的任何东西, Joe-E 验证器将此标记为错误。

驯服有助于消除环境权限,因为它确保提供环境权限的库方法不会 可访问 Joe-E 程序。我们也用驯服来暴露 仅提供能力规则的 Java 库子集。

【讨论】:

  • 如果字节码静态分析可以将 API 位列入白名单,那将会很有趣。虽然很棘手。 /File 是一个有趣的。它应该代表一个文件路径字符串。所有具有安全检查的方法都会带来危险。 (File 实际上并不是一成不变的。
  • @TomHawtin-tackline,一些静态流分析可以通过暴露缺失的源来帮助调试白名单,例如将new java.io.FileInputStream(String, String) 视为接收器,并确保到达它的所有字符串都被白名单识别为系统资源。鉴于java.lang.reflect.Method 的存在和opaque predicates 的制作容易,它永远不会完整,可能不会接近保守。
  • Java 反射不会在白名单上。我不记得 Joe-E 是否这样做了,但是一些对象能力语言通过邀请支持反射(代码可以创建一个具有反射访问权限的对象,就好像它是创建它的代码一样 - 然后可以将其传递给更通用的代码)。同样,任何使用反射的代码都将难以列入白名单。即使是使用可变静态的代码(例如private static final char[])也会有很大的问题。
  • @TomHawtin-tackline,我认为你是对的。 IIRC Joe-E 提供了一种减弱的替代方案,而不是驯服。 Mark Miller 喜欢动态类型系统的原因有很多,但其中一个原因是,当一个对象只是一条记录时,作者往往不会通过错误地假设只有通过静态类型可用的运算符可用而泄露权限。
【解决方案2】:

我会尝试模拟 Java 小程序沙盒模型。如果沙盒足够安全,可以在我的 PC 上运行来自 Internet 的任意代码,那么它对于您的用户脚本应该足够安全。好吧,您可能不希望用户脚本弹出一些 GUI 窗口,因此您需要限制权限而不是小程序沙箱。

【讨论】:

  • 用户脚本通常是由天真的开发人员编写的,并且与调用它们的应用程序相比,审查起来更不仔细,因此比核心代码库更容易出现脚本注入等confused deputy漏洞。
  • OP 希望支持用户脚本并想知道如何安全地做到这一点。
  • 同意。 OP 尝试授予用户脚本足够的权限来完成他们的工作是明智的,但由于脚本作者的天真以及较低的审查和测试标准,因此仅此而已。
【解决方案3】:

我怀疑您会发现,与其从通用编程语言开始并弄清楚如何让人们访问它并使其安全,不如换一种方式更安全。

我的方法是从特定领域的语言开始,并为其提供对沙盒的访问权限 - 您愿意并乐于让模组制作者影响的程序环境的各个方面。

【讨论】:

  • 唉,我既没有时间开发自己的特定领域语言,也没有影响人们学习它只是为了在我的游戏中进行修改的影响力。不幸的是,这是我必须“尽最大努力”尝试安全性的情况之一,既是为了便于修改者采用该语言,又是为了我自己在没有无限预算和时间的情况下开发软件的能力。
  • @Hawkwing 很公平。祝你好运。
  • Mike Samuel 的回答提到了 Joe-E,它是 Java 的一个安全子集。这似乎是一个更好的方法。然而,困难的是图书馆。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-02
相关资源
最近更新 更多