简介
Jython在JVM中运行并带有安全管理器。 安全管理器不应阻止Jython引擎本身完成其工作,但不应允许在Jython中运行的Python脚本执行任何特权操作。 到底使用什么最小的Java安全策略可以实现这一点?
换句话说(完整版)
本问题涉及使用Java的安全机制来对不受信任的Python脚本进行隔离。(我不想讨论其他隔离Python的方法)。 如果这种安全方法存在根本缺陷,请说明。
不受信任的Python代码将调用可信Java对象上的方法,并嵌入到Java中作为PyObject。 这在Jythonbook的示例中有所解释,并且我们将使用该示例中的代码。 这是在Java 1.6上的Jython 2.5.2。
我们需要向安全管理器提供一些非常具体的指示,因为Jython会执行一些特权操作,但它还会执行不受信任的Python代码,这些代码不应具有任何特权。
首先,为了安全起见,我们在Java VM中安装了SecurityManager:
/home/me% export CLASSPATH=.:jython.jar
/home/me% javac ./org/jython/book/interfaces/BuildingType.java ./org/jython/book/Main.java ./org/jython/book/util/BuildingFactory.java
/home/me% java org.jython.book.Main
Building Info: null BUILDING-A 100 WEST MAIN
Building Info: null BUILDING-B 110 WEST MAIN
Building Info: null BUILDING-C 120 WEST MAIN
好的。但对于我们来说,Building.py是不受信任的代码,所以我们锁定了JVM。问题是,这会瘫痪Jython:
/home/me% java -Djava.security.manager org.jython.book.Main
Jul 23, 2013 7:07:17 PM org.python.google.common.base.internal.Finalizer getInheritableThreadLocalsField
INFO: Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will inherit thread local values.
Exception in thread "main" java.security.AccessControlException: access denied (java.util.PropertyPermission user.dir read)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
...
at java.io.File.getAbsolutePath(File.java:501)
at org.python.core.PySystemState.<init>(PySystemState.java:181)
at org.python.core.PySystemState.doInitialize(PySystemState.java:890)
at org.python.core.PySystemState.initialize(PySystemState.java:800)
at org.python.core.PySystemState.initialize(PySystemState.java:750)
at org.python.core.PySystemState.initialize(PySystemState.java:743)
at org.python.core.PySystemState.initialize(PySystemState.java:737)
at org.python.core.PySystemState.initialize(PySystemState.java:733)
at org.python.core.ThreadStateMapping.getThreadState(ThreadStateMapping.java:17)
at org.python.core.Py.getThreadState(Py.java:1315)
at org.python.core.Py.getThreadState(Py.java:1311)
at org.python.core.Py.getSystemState(Py.java:1331)
at org.python.util.PythonInterpreter.<init>(PythonInterpreter.java:102)
at org.python.util.PythonInterpreter.<init>(PythonInterpreter.java:92)
at org.python.util.PythonInterpreter.<init>(PythonInterpreter.java:64)
at org.jython.book.util.BuildingFactory.<init>(BuildingFactory.java:22)
at org.jython.book.Main.main(Main.java:21){code}
安全管理器不允许任何人读取 "user.dir" 属性。当然,Jython 本身应该可以读取该属性。我能否像这样将其写入策略文件中?
/home/me% cat jython.policy
grant codeBase "/home/me/*" {
permission java.util.PropertyPermission "user.dir", "read";
};
/home/me% java -Djava.security.manager -Djava.security.policy=jython.policy org.jython.book.Main
不,我不能这样做…因为不可信的python代码也在python解释器类中运行。因此,不受信任的Python也会获得这种特权,这是不好的。
因此,我需要授权仅限于特定的jython类,例如PySystemState。(我可能还需要编辑其源代码,使其在doPrivilegedAction
调用中运行某些代码。)
太好了。下一个所需的权限非常棘手:危险的createClassLoader权限。
java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:594)
at java.lang.ClassLoader.<init>(ClassLoader.java:226)
at java.security.SecureClassLoader.<init>(SecureClassLoader.java:76)
at java.net.URLClassLoader.<init>(URLClassLoader.java:113)
at org.python.core.BytecodeLoader$Loader.<init>(BytecodeLoader.java:81)
at org.python.core.BytecodeLoader.makeClass(BytecodeLoader.java:27)
at org.python.core.BytecodeLoader.makeCode(BytecodeLoader.java:67)
at org.python.compiler.LegacyCompiler$LazyLegacyBundle.loadCode(LegacyCompiler.java:43)
at org.python.core.CompilerFacade.compile(CompilerFacade.java:34)
at org.python.core.Py.compile_flags(Py.java:1703)
at org.python.core.Py.compile_flags(Py.java:1708)
at org.python.core.Py.compile_flags(Py.java:1738)
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:206)
at org.jython.book.util.BuildingFactory.<init>(BuildingFactory.java:23)
at org.jython.book.Main.main(Main.java:22)
在堆栈的底部,我们看到
PythonInterpreter.exec
触发了此访问请求。 exec()
必须作为PrivilegedAction运行吗?因此,这个发现过程可能会持续一段时间,我希望有人能简单地知道答案:Jython中哪些类需要授权,以及它们需要什么特定的权限?
如果这种方法注定要失败,那么一个这样的答案将是很好的。