沙盒防止Java应用程序中的恶意代码(Sandbox against malicious code in a Java application)

编程入门 行业动态 更新时间:2024-10-27 08:26:35
沙盒防止Java应用程序中的恶意代码(Sandbox against malicious code in a Java application)

在允许用户提交自己要由服务器运行的代码的模拟服务器环境中,显而易见的是,任何用户提交的代码都可以在沙箱中运行,而不像Applet在浏览器中。 我想要能够利用JVM本身,而不是添加另一个VM层来隔离这些提交的组件。

这种限制似乎是可能的,使用现有的Java沙箱模型,但是有一种动态的方式来为只有用户提交的运行应用程序的部分启用它?

In a simulation server environment where users are allowed to submit their own code to be run by the server, it would clearly be advantageous for any user-submitted code to be run in side a sandbox, not unlike Applets are within a browser. I wanted to be able to leverage the JVM itself, rather than adding another VM layer to isolate these submitted components.

This kind of limitation appears to be possible using the existing Java sandbox model, but is there a dynamic way to enable that for just the user-submitted parts of a running application?

最满意答案

在自己的线程中运行不受信任的代码。 这例如可以防止无限循环等问题,并使未来的步骤更容易。 主线程等待线程完成,如果需要太长时间,请用Thread.stop将其删除。 Thread.stop已被弃用,但由于不受信任的代码不能访问任何资源,因此可以安全地杀死它。

在该线程上设置SecurityManager 。 创建一个SecurityManager的子类,该子类覆盖了checkPermission(Permission perm),以简单地为所有权限抛出一个SecurityException ,除了少数几个。 有一系列方法及其所需的权限: Java TM 6 SDK中的权限 。

使用自定义ClassLoader加载不受信任的代码。 您的类加载器将被调用不受信任代码使用的所有类,因此您可以执行禁止访问单个JDK类的操作。 要做的是有一个允许的JDK类的白名单。

您可能希望在单独的JVM中运行不受信任的代码。 虽然以前的步骤将使代码安全,但隔离代码仍然可以做一个令人讨厌的事情:分配尽可能多的内存,这将导致主应用程序的可见占用增长。

JSR 121:应用程序隔离API规范旨在解决这个问题,但不幸的是它还没有实现。

这是一个非常详细的主题,我主要是把这一切写在我头顶上。

但无论如何,一些不完美的,使用自己的风险,可能是buggy(伪)代码:

类加载器

class MyClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name is white-listed JDK class) return super.loadClass(name); return findClass(name); } @Override public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the untrusted class data here } }

安全管理器

class MySecurityManager extends SecurityManager { private Object secret; public MySecurityManager(Object pass) { secret = pass; } private void disable(Object pass) { if (pass == secret) secret = null; } // ... override checkXXX method(s) here. // Always allow them to succeed when secret==null }

线

class MyIsolatedThread extends Thread { private Object pass = new Object(); private MyClassLoader loader = new MyClassLoader(); private MySecurityManager sm = new MySecurityManager(pass); public void run() { SecurityManager old = System.getSecurityManager(); System.setSecurityManager(sm); runUntrustedCode(); sm.disable(pass); System.setSecurityManager(old); } private void runUntrustedCode() { try { // run the custom class's main method for example: loader.loadClass("customclassname") .getMethod("main", String[].class) .invoke(null, new Object[]{...}); } catch (Throwable t) {} } }

Run the untrusted code in its own thread. This for example prevents problems with infinite loops and such, and makes the future steps easier. Have the main thread wait for the thread to finish, and if takes too long, kill it with Thread.stop. Thread.stop is deprecated, but since the untrusted code shouldn't have access to any resources, it would be safe to kill it.

Set a SecurityManager on that Thread. Create a subclass of SecurityManager which overrides checkPermission(Permission perm) to simply throw a SecurityException for all permissions except a select few. There's a list of methods and the permissions they require here: Permissions in the JavaTM 6 SDK.

Use a custom ClassLoader to load the untrusted code. Your class loader would get called for all classes which the untrusted code uses, so you can do things like disable access to individual JDK classes. The thing to do is have a white-list of allowed JDK classes.

You might want to run the untrusted code in a separate JVM. While the previous steps would make the code safe, there's one annoying thing the isolated code can still do: allocate as much memory as it can, which causes the visible footprint of the main application to grow.

JSR 121: Application Isolation API Specification was designed to solve this, but unfortunately it doesn't have an implementation yet.

This is a pretty detailed topic, and I'm mostly writing this all off the top of my head.

But anyway, some imperfect, use-at-your-own-risk, probably buggy (pseudo) code:

ClassLoader

class MyClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name is white-listed JDK class) return super.loadClass(name); return findClass(name); } @Override public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the untrusted class data here } }

SecurityManager

class MySecurityManager extends SecurityManager { private Object secret; public MySecurityManager(Object pass) { secret = pass; } private void disable(Object pass) { if (pass == secret) secret = null; } // ... override checkXXX method(s) here. // Always allow them to succeed when secret==null }

Thread

class MyIsolatedThread extends Thread { private Object pass = new Object(); private MyClassLoader loader = new MyClassLoader(); private MySecurityManager sm = new MySecurityManager(pass); public void run() { SecurityManager old = System.getSecurityManager(); System.setSecurityManager(sm); runUntrustedCode(); sm.disable(pass); System.setSecurityManager(old); } private void runUntrustedCode() { try { // run the custom class's main method for example: loader.loadClass("customclassname") .getMethod("main", String[].class) .invoke(null, new Object[]{...}); } catch (Throwable t) {} } }

更多推荐

本文发布于:2023-08-05 17:07:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1436033.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:应用程序   恶意代码   Java   Sandbox   application

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!