Sandbox against malicious code in a Java application
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) {}
}
}
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
The Difference Between the Runnable and Callable Interfaces in Java
Difference Between Validate(), Revalidate() and Invalidate() in Swing Gui
How to Pass a Primitive Data Type by Reference
Static Nested Class in Java, Why
Java - How Would I Dynamically Add Swing Component to Gui on Click
How Do Synchronized Static Methods Work in Java and How to Use It for Loading Hibernate Entities
Killing Thread After Some Specified Time Limit in Java
How to Get the X and Y of a Program Window in Java
What's the Difference Between Getpath(), Getabsolutepath(), and Getcanonicalpath() in Java
Jtable How to Refresh Table Model After Insert Delete or Update the Data
How to Run Testng from Command Line
Reversing a Linked List in Java, Recursively
Why Does the Jvm Still Not Support Tail-Call Optimization
Why Not to Start a Thread in the Constructor? How to Terminate
How to Remove the Last Character from a String
Using a Custom Truststore in Java as Well as the Default One