我正在使用Eclipse中的Java项目,该项目使用Mozilla Rhino(不是捆绑的JDK rhino)来执行可能不受信任的代码。为此,我构建了一个不允许文件访问或许多其他危险操作的安全管理器。
安全管理器对任何操作都是开放的,直到执行脚本本身,然后锁定只是为了执行本身,在之后立即解锁:
Object lock = new Object();
MyAppCustomSecurityManager.instance.lock(lock, ThreadContext.CONTEXT_SCRIPT);
sc.exec(this.cx, this.globalScope);
MyAppCustomSecurityManager.instance.unlock(lock);
我最近已经达到了可以在框架上运行脚本的程度,并开始从我的homespun安全管理器获取消息:
阻止文件读取:
[project]\target\classes\org\mozilla\javascript\WrapFactory.class
涉及一堆特定于Rhino的类。
我没有看到安全管理员提供的与创建或设置类加载器有关的任何与安全相关的日志条目。
项目类由sun.misc.Launcher$AppClassLoader
加载。该类加载器也由ClassLoader.getSystemClassLoader()
和Thread.currentThread().getContextClassLoader()
返回。
当我在maven中运行时,我首先使用mvn package
和maven-shade-plugin
来获取“阴影”JAR。然后我使用java -jar
执行该JAR,并发现问题不再存在且脚本运行成功(但安全,因为任何实际打开文件的尝试都会被过滤)。我注意到调试语句报告的类加载器是相同的,这使我相信有另一个类加载器,可能是URLClassLoader
参与尝试在Eclipse中运行它,但我无法找到它,除了在堆栈跟踪在库代码中的一个尴尬的地方我无法真正添加调试语句。
显然我可以在Maven中测试,但这并不理想,因为我失去了Eclipse的快速周转和调试器。
我考虑的解决方案是:
检测是否在Eclipse中运行,并禁用安全管理器。这似乎是一种不好的做法,需要配置确实通过git传输,因为我们已经.project
gitignored,并且正如我在另一篇文章中所读到的那样:
实际上代码不是在Eclipse中运行,而是在Eclipse启动的单独Java进程中运行,并且默认情况下Eclipse没有做任何事情使它与程序的任何其他调用有任何不同。
这对我来说非常奇怪,因为编译jar的独立执行很好。
实际上,mvn exec:java
似乎也被打破了,可能是因为这些类没有放入Jar中。
允许打开类路径中的文件:
同样值得怀疑的是,因为人们可以给出包含..
的名称并将其标准化将会很困难。类路径还可以包含我不希望脚本直接看到的内容,例如某些属性文件。
让Eclipse通过外部工具调用我的jar 这需要一个相当长的两步构建过程,并会降低生产力。
此应用程序设计为在Jar中运行,但任何使非jar执行不安全的解决方案也存在风险,因为我不确定任何用户可能需要运行它由于其他情况。一个应用程序在像这样的jar之外运行时会出现问题,这似乎很奇怪。
我还尝试通过运行打印到控制台的可信脚本来“预热”Rhino,但这只会延迟问题直到我的脚本尝试加载它应该加载的类。
堆栈跟踪如下:
Exception in thread "main" java.lang.NoClassDefFoundError: net/myapp/scripting/NodePosition
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2521)
at java.lang.Class.privateGetPublicMethods(Class.java:2641)
at java.lang.Class.getMethods(Class.java:1457)
at org.mozilla.javascript.JavaMembers.discoverAccessibleMethods(JavaMembers.java:380)
at org.mozilla.javascript.JavaMembers.discoverAccessibleMethods(JavaMembers.java:335)
at org.mozilla.javascript.JavaMembers.reflect(JavaMembers.java:450)
at org.mozilla.javascript.JavaMembers.<init>(JavaMembers.java:76)
at org.mozilla.javascript.JavaMembers.lookupClass(JavaMembers.java:838)
at org.mozilla.javascript.NativeJavaObject.initMembers(NativeJavaObject.java:90)
at org.mozilla.javascript.NativeJavaObject.<init>(NativeJavaObject.java:80)
at org.mozilla.javascript.NativeJavaObject.<init>(NativeJavaObject.java:70)
at org.mozilla.javascript.WrapFactory.wrapAsJavaObject(WrapFactory.java:149)
at org.mozilla.javascript.WrapFactory.wrap(WrapFactory.java:105)
at org.mozilla.javascript.ScriptRuntime.toObject(ScriptRuntime.java:962)
at org.mozilla.javascript.ScriptRuntime.toObjectOrNull(ScriptRuntime.java:918)
at org.mozilla.javascript.ScriptRuntime.getPropFunctionAndThis(ScriptRuntime.java:2213)
at org.mozilla.javascript.gen.c2._c0(net.myapp.servercore.LocalFile@2ff95fc4:0)
at org.mozilla.javascript.gen.c2.call(net.myapp.servercore.LocalFile@2ff95fc4)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:398)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3065)
at org.mozilla.javascript.gen.c2.call(net.myapp.servercore.LocalFile@2ff95fc4)
at org.mozilla.javascript.gen.c2.exec(net.myapp.servercore.LocalFile@2ff95fc4)
at net.myapp.servercore.ScriptEnv.runScript(ScriptEnv.java:114)
at net.myapp.servercore.MyAppMain.<init>(MyAppMain.java:105)
at net.myapp.servercore.MyAppMain.main(MyAppMain.java:129)
Caused by: java.lang.ClassNotFoundException: net.myapp.scripting.NodePosition
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 26 more
答案 0 :(得分:2)
我设法通过更新我的安全管理器来解决这个问题,以允许在类路径.class
的子目录中打开net.myapp.scripting
文件,这是存储脚本所需类的地方。我也通过运行一个可以加载我需要的任何Rhino类(包括数组)的短脚本来“升温”Rhino。
java.util
类工作得很好,来自rt.jar
。
然而,这似乎是一种容易出现安全问题的解决方法,所以我有兴趣看到更好的解决方案。