我遇到一个问题,在nashorn下运行的一些相当简单的代码正在查找系统属性。查找系统属性失败,显示AccessControlException
。
我的安全政策已经允许:
grant {
permission java.util.PropertyPermission "*", "read, write";
};
在使用-Djava.security.debug=access,failure
进行调试时,我发现CodeSource
null
对于有问题的ProtectionDomain
是jdk.nashorn.internal.runtime.Source
。
我将断点移到了构造函数中,经过几层间接后,我最终设法将问题跟踪到private Source(String name, String base, char[] content, URL url) {
this.name = name;
this.base = base;
this.content = content;
this.length = content.length;
this.url = url;
}
。
NashornScriptEngine
有一个null
正在调用的公共构造函数,它最终将url设置为public Source(String name, char[] content) {
this(name, baseName(name, (String)null), content, (URL)null);
}
public Source(String name, String content) {
this(name, content.toCharArray());
}
,这是我看到代码通过的构造函数。
CodeSource
虽然我们确实将脚本作为字符串传递,但它是从HTML文件的代码块中提取的,所以理论上我可以为它提供public Source(String name, URL url, Charset cs) throws IOException {
this(name, baseURL(url, (String)null), readFully(url, cs), url);
}
。然后希望访问控制代码至少可以给它最低级别的信任,并且希望查找系统属性。
我看到做传递URL的其他构造函数。 e.g:
ScriptEngine
对于我的生活,我无法弄清楚如何与ScriptEngine#eval
进行互动,以鼓励nashorn引擎调用其中一个更好的构造函数。 String
只有Reader
或FILENAME
的方法。有没有办法做到这一点?还有另一种方法可以确保在nashorn创建代码时正确设置CodeSource吗?
我知道它不是 - 在脚本上下文中设置{{1}}。这似乎完全被忽略了。
奇怪的是,我们也在JRuby下运行所有相同类型的测试,但我们在那里看不到同样的问题。所以无论发生什么,这对nashorn来说都是特别的。 (FWIW,我们从未在Rhino下看到过这种情况。)
答案 0 :(得分:2)
提供CodeSource
是一种安全功能。攻击者可以使用它来错误地声称JS代码来自特权位置,因此将其置于任何保护域中。 Nashorn只会将CodeSource
与通过URL加载的代码相关联(因此可以确定它来自何处)。即使在Java中,将代码与其源关联也只允许类加载器执行,因此它受createClassLoader
运行时权限的保护。 Its documentation甚至说:
“这是非常危险的许可。恶意 那么可以实例化自己的类加载器的应用程序 将自己的流氓类加载到系统中。这些新装 类可以放在任何保护域中 loader,从而自动授予类的权限 那个域。“
将“class”替换为“script”,您在此处也有同样的疑虑。
我可以看到Nashorn有一个同时使用CodeSource
和char[]
的构造函数,但它必须对createClassLoader
进行权限检查或者新的定制运行时权限
答案 1 :(得分:1)
您可以使用jdk.nashorn.api.scripting.URLReader(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/URLReader.html)将URL包装为Reader。使用URLReader,nashorn将从该URL加载脚本并关联正确的CodeSource - 以便您对该URL的安全策略有效。
答案 2 :(得分:1)
文件:Main.java
import javax.script.*;
public class Main {
public static void main(String[] ar) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
System.out.println(e.eval("java.lang.System.getProperty('foo.bar')"));
}
}
档案:foo.policy
grant {
permission java.util.PropertyPermission "*", "read, write";
};
命令:
javac Main.java
java -Djava.security.manager -Dfoo.bar = sss -Djava.security.policy = foo.policy Main
“sss”按预期打印(使用jdk 1.8.0 update 40)