我有一个 java 应用程序,它在某些部分使用 JNI 来完成一些工作。它遵循通常的 DLL 加载,然后调用 DLL 的本机方法。有什么方法可以限制本机方法可以从 Java 应用程序执行的操作吗?例如,我们是否可以限制 DLL 不打开任何文件或不打开任何套接字,即使它有执行此操作的代码?它可以禁止它为执行某些操作而加载的 DLL,可能是通过登录某些内容或引发异常。
4 回答
不,你不能。DLL 作为一个整体被加载,然后 Java 端无法控制本机代码在做什么。
一种解决方案可能是中间人。这将涉及编写一个与原始 DLL 具有相同接口的“shell”DLL。例如,您可以通过将“shell”DLL 放在特定位置并使用该java.library.path
属性来告诉 Java 加载它。那么“shell”DLL 的作用就是通过沙箱化和重定向标准函数来加载“真正的”DLL。这听起来很痛苦,而且这会发生在本机方面,而不是来自 Java。
2021 年编辑:今天还需要指出的是,运行 Java 的沙箱可能是虚拟机,在云中、Docker 或其他设备中,处于锁定配置中。
我非常喜欢Gregory Pakosz的回答。但是,您可以做的是对 Java 实例本身进行沙箱处理。在受限上下文中启动 Java 应用程序本身。
在 Windows 或 Unix 中,您可以创建一个受限于某个目录并且只能访问某些 DLL 的用户。因此,从 JNI 调用的 DLL 可以为所欲为,但不会走得太远,因为 Java 运行的用户不能做很多事情。
如果您的 Java 程序需要执行特权操作,那么它的 Java 端将不得不与另一个程序(无论是否是 Java)进行对话,以便为它执行特权操作。
请记住,如果您不能信任 DLL,那么您也不能再信任 Java 代码,因为 DLL 可能已经“入侵”了 Java 机器。另一方面,任何讨厌的东西都不应该能够突破他们运行的用户的限制。(除非配置错误或操作系统中的错误。)
通常您会在 Java 安全管理器下运行您的应用程序,但我认为它不会对通过 JNI 运行的代码产生任何影响。
您可以实现 JNI 代码可以获得的某种设置。例如,在 UNIX 系统上,您可以为特殊类型的权限创建组,并检查当前用户是否具有所需的权限,否则只返回 0 或其他内容。