Sandbox Against Malicious Code in a Java Application

Sandbox against malicious code in a Java application

  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.

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

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

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

Sandbox Java code before compiling?

Java has some sandboxing mechanisms, but those have such a poor security track record that many recommend turning off Java in the browser entirely.

You could try sandboxing a VM inside it's own virtual OS with reduced privileges.

Alternatively, you could require the code to be run in a language like
Joe-E that is designed to allow Java programs to execute untrusted code.

Joe-E is a subset of Java that makes it easier to architect and implement programs with strong security properties that can be checked during a security review. It enables programmers to apply the principle of least privilege to their programs; implement application-specific reference monitors that cannot be bypassed; introduce and use domain-specific security abstractions; safely execute and interact with untrusted code; and build secure, extensible systems. Joe-E demonstrates how it is possible to achieve the strong security properties of an object-capability language while retaining the features and feel of a mainstream object-oriented language.

The degree to which Joe-E's designers had to depart from standard Java should give you an idea of how big a task it is to prevent untrusted Java code from abusing the ambient authority available from within a JVM.


While some of these approaches may protect you from abuse of authority (especially if layered together), none will prevent denial of service. If you're trying to run other people's code alongside your code, and it decides to try to take all the CPU and never give it back, your only option is often to kill the whole process.

How do I create a Java sandbox?

You are looking for a security manager. You can restrict the permissions of an application by specifying a policy.

How to run java code in a restricted sandbox (without network, filesystem access)

You can control the environment using policy files
http://docs.oracle.com/javase/1.4.2/docs/guide/security/PolicyFiles.html#Examples (archived version @archive.org)

you could run then run your jar

java -Djava.security.manager -Djava.security.policy=/path/your_policy_file.policy -jar

Does Java have a built-in Antivirus? Is it true?

Java does have a security-related concept called "sandbox", but it works very differently from typical anti-virus products. The latter usually try to catch viruses via signatures or code analysis before they are executed.

The Java sandbox on the other hand allows you to run Java code while witholding from it access to system resources that could be used to to bad things, e.g. no access to any files.

However, only Java applets and Java Web Start applications run in a sandbox per default. Regular java applications have full access to your system.

Creating a sandboxed plugin-extensible application in Java

You should look into using a Security Manager, and perhaps defining some of your own permissions. There is already a set of commonly used permissions you can use when defining policies.

Note that read-only access to an RDBMS is unlikely to be within the scope of your Java environment. Instead, this is typically handled using a separate RDBMS user with specific permissions there. Your framework would need to connect to the DB using that user name.

Java security: Sandboxing plugins loaded via URLClassLoader

From the docs:

The AccessControlContext of the thread that created the instance of URLClassLoader will be used when subsequently loading classes and resources.

The classes that are loaded are by default granted permission only to access the URLs specified when the URLClassLoader was created.

The URLClassLoader is doing exactly as its says, the AccessControlContext is what you need to be looking at. Basically the thread that is being referenced in AccessControlContext does not have permissions to do what you think it does.



Related Topics



Leave a reply



Submit