在我们的应用程序中,用户能够定义由我们的主引擎执行的 Java 表达式(这些表达式只是方法调用:例如 Math.abs(42) )。它们是通过反射执行的。
有哪些不同的解决方案可以直接或通过最终在内部调用 System.exit 的方法调用来防止那些表达式调用例如 System.exit (但还有文件访问和其他......)?
请注意,可以在不同的线程中执行几个不同的表达式。例如,使用 SecurityManager 阻止文件访问不起作用,因为在执行表达式时主引擎必须仍然能够访问文件系统。
在我们的应用程序中,用户能够定义由我们的主引擎执行的 Java 表达式(这些表达式只是方法调用:例如 Math.abs(42) )。它们是通过反射执行的。
有哪些不同的解决方案可以直接或通过最终在内部调用 System.exit 的方法调用来防止那些表达式调用例如 System.exit (但还有文件访问和其他......)?
请注意,可以在不同的线程中执行几个不同的表达式。例如,使用 SecurityManager 阻止文件访问不起作用,因为在执行表达式时主引擎必须仍然能够访问文件系统。
你说你不能使用是错误的SecurityManager
——这正是它的用途:托管不受信任的代码,如在 Applet 容器或 RMI 服务器中。现代的 SecurityManager 配置了策略文件,这些文件授予特定的细粒度权限,包括对文件系统的有限访问。您需要使用 SecurityManager,但您需要成为它的专家。
这是一个巨大的话题;最好的办法是谷歌“Java 安全策略文件”并阅读所有你能读到的东西。
你在做什么是疯狂的。允许用户在你的机器上执行任意 Java 代码是一个糟糕的想法,而且你无法确保它对知道他们的东西的黑客安全。
我能想到的唯一解决方案是创建一个可能使用的包和方法的白名单。但是尝试将特定操作列入黑名单永远不会让您到达那里。在破坏东西方面,总会有人比你更聪明。
更新:我现在已经阅读了更多关于SecurityManager
它的信息,而且您似乎可以很好地控制包访问,所以我建议您使用 Ernest 的回答。
Java 安全系统是用于此目的的合适工具。SecurityManager
只是您必须使用的该系统的一部分。
基本上,您不会自己调用不受信任的代码。相反,您将该调用包装成 aPrivilegedAction
并将其提供给其中一个AccessController.doPrivileged
方法。然后不受信任的代码将在另一个ProtectionDomain
.
因此,您必须配置两个保护域:一个用于具有完全权限的引擎,另一个用于具有降低权限的不受信任的代码。
但正如欧内斯特已经提到的:这是相当复杂的东西,不适合像这样的问答网站。阅读 Oracle 和 Co. 提供的相应教程。使用上述关键字进行搜索。
例如 Apache Velocity 有一个类似的问题需要解决。他们使用velocity.properties中定义的黑名单类和包:
# ----------------------------------------------------------------------------
# SECURE INTROSPECTOR
# ----------------------------------------------------------------------------
# If selected, prohibits methods in certain classes and packages from being
# accessed.
# ----------------------------------------------------------------------------
introspector.restrict.packages = java.lang.reflect
# The two most dangerous classes
introspector.restrict.classes = java.lang.Class
introspector.restrict.classes = java.lang.ClassLoader
# Restrict these for extra safety
introspector.restrict.classes = java.lang.Compiler
introspector.restrict.classes = java.lang.InheritableThreadLocal
introspector.restrict.classes = java.lang.Package
introspector.restrict.classes = java.lang.Process
introspector.restrict.classes = java.lang.Runtime
introspector.restrict.classes = java.lang.RuntimePermission
introspector.restrict.classes = java.lang.SecurityManager
introspector.restrict.classes = java.lang.System
introspector.restrict.classes = java.lang.Thread
introspector.restrict.classes = java.lang.ThreadGroup
introspector.restrict.classes = java.lang.ThreadLocal
Java中有太多东西可能会导致您可能没有意识到的问题。最安全的做法是创建一个允许的类列表,并通过自定义类加载器在单独的进程中运行这些类(这样你就可以安全地杀死它)
对于大多数人甚至不知道的严重危险代码,请查看sun.misc.Unsafe,它可以让您