针对 Java 应用程序中恶意代码的沙箱 [英] Sandbox against malicious code in a Java application

查看:26
本文介绍了针对 Java 应用程序中恶意代码的沙箱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在允许用户提交自己的代码以供服务器运行的模拟服务器环境中,任何用户提交的代码在沙箱中运行显然是有利的,这与 Applets 在浏览器中不同.我希望能够利用 JVM 本身,而不是添加另一个 VM 层来隔离这些提交的组件.

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.

使用现有的 Java 沙箱模型似乎可以实现这种限制,但是否有一种动态方法可以仅针对正在运行的应用程序的用户提交部分启用该限制?

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?

推荐答案

  1. 在自己的线程中运行不受信任的代码.例如,这可以防止无限循环等问题,并使以后的步骤更容易.让主线程等待线程完成,如果时间过长,用 Thread.stop 杀死它.Thread.stop 已弃用,但由于不受信任的代码不应访问任何资源,因此可以安全地杀死它.

  1. 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.

设置SecurityManager在那个线程上.创建一个 SecurityManager 的子类,它覆盖 checkPermission(Permission perm) 简单地抛出一个 SecurityException 适用于除少数权限之外的所有权限.这里有一个方法列表和它们需要的权限:Permissions在 JavaTM 6 SDK 中.

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.

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

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.

您可能希望在单独的 JVM 中运行不受信任的代码.虽然前面的步骤可以使代码安全,但孤立的代码仍然可以做一件烦人的事情:分配尽可能多的内存,这会导致主应用程序的可见占用空间增加.

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:应用程序隔离 API 规范 旨在解决这个问题,但是不幸的是,它还没有实现.

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:

类加载器

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) {}
  }
}

这篇关于针对 Java 应用程序中恶意代码的沙箱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆