2

If there is a system where the client writes Java code (*.java files), and submits them to a server running in Java, how can I make the submitted code not do unwanted and malicious things?

For a little more depth: The client would write the plain text Java code (their classes), and the code would be sent to the server. On the server, the code would be inspected to make sure it only does allowed actions. If it passes the test, it gets compiled into a .class file, where it is then loaded with Java's class loader. Finally, using Reflection, methods can then be called and passed parameters.

I think I can see how to do most of that, but how do I make sure code that's compiled is "safe"? For example, I wouldn't want it to spawn threads, or perform file IO, or interact with the system it's running on in any way. I was thinking that I could scan the input file for imports, and if they are not on a white list, reject the file. On top of that, I was thinking that if I did want to limit something, like say the number of threads, I could allow the import of a proxy class that would keep track of threads per user.

Would that work, or if not is there a way?

djechlin
  • 59,258
  • 35
  • 162
  • 290
contrapsych
  • 1,919
  • 4
  • 29
  • 44
  • 2
    This might be helpful for you. http://stackoverflow.com/questions/502218/sandbox-against-malicious-code-in-a-java-application?rq=1 – Syd Dec 25 '13 at 04:18
  • Look at the Securiy Manager – Thorbjørn Ravn Andersen Dec 25 '13 at 04:21
  • @Syd Thanks for that. I have looked around with Google and on SO, but any combination of Java and plugin I used seemed to only give me results about web browser plugins. Again, thank you. – contrapsych Dec 25 '13 at 04:22
  • @ThorbjørnRavnAndersen The `SeurityManager` really only covers a small part of what the server needs for its protection. See [this answer](http://stackoverflow.com/q/19067161/418556) for details. *"Again, thank you."* Tip: Add the `@` notation seen at the start od this comment, to *notify* someone of a new comment. Also note that any Java application that does not normally run with a `SecurityManager` can create one. – Andrew Thompson Dec 25 '13 at 05:28
  • @AndrewThompson The SecurityManager is the place to start when doing things like this. Hopefully it will show that it is not easy running arbitrary code in a controlled fashion. After thinking it over the only reliable way to do this - in my opinion - is not to use a full JVM. You must do what Google did with their application engine, and create a special JVM restricted to what you want it to do. – Thorbjørn Ravn Andersen Dec 26 '13 at 11:35

5 Answers5

3

What you are trying to do would be a never ending battle with people who choose to do malicious stuff. I would therefore recommend that you look at this page on how to sandbox your code.

http://securesoftwaredev.com/2012/11/12/sandboxing-java-code/

To summarize

  • By default, Java runs without a SecurityManager, so you should add code to your application to enable one:

    System.setSecurityManager(new SecurityManager());
    
  • A permission represents access to a system resource.

  • Use Code signing

To assemble the pieces in a sandbox:

  1. Install a SecurityManager
  2. Sign the application jars
  3. Grant all code signed by us AllPermission
  4. Add permission checks in places that code may call
  5. Run the code after the permission checks in a doPrivileged() block
djechlin
  • 59,258
  • 35
  • 162
  • 290
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
  • From reading the Security Manager documentation, it appears that it works only in the thread that's calling the function (which I find to be good). Does that mean that using a security manager wouldn't affect the rest of the system that has nothing to do with what I'm trying to do? – contrapsych Dec 25 '13 at 04:43
  • @JAKE6459, ["Comparing Java and .NET Security"](http://web.eecs.utk.edu/~pauln/papers/computers_and_security-net-java.pdf) charts the frequency of exploits against the SecurityManager. Many suggest turning Java off in browsers because the SecurityManager has not successfully defended the browser against Java code, so Java's SecurityManager is widely considered a failure. – Mike Samuel Dec 25 '13 at 05:01
  • It is my understanding that the security manager can either be for a JVM or all JVM. So as @Mike is suggesting, running this code in a JVM in its own VM may be prudent. Mike also keeps on mentioning Browser, but I am not sure from your original Question whether this is in fact going to run in a Browser? – Scary Wombat Dec 25 '13 at 05:05
  • @Mike, your links seems rather old – Scary Wombat Dec 25 '13 at 05:07
  • @user2310289, It's not that old -- the data in that article goes to 2011. I mention the browser only because it's the largest arena in which the Java SecurityManager has been exposed to malicious code. There are no other arenas where it has been exposed to malicious code on the same scale, so in the only contested arena where it was the chief security mechanism it has failed to inspire confidence. – Mike Samuel Dec 25 '13 at 05:25
  • -1... this is basically a link-only answer, i.e. if the link breaks I would flag it for deletion. Please at least include some of the information in the linked article or just post this as comment. – djechlin Dec 25 '13 at 05:30
  • @djechlin I totally agree with you. My answer have been updated. – Scary Wombat Dec 25 '13 at 05:39
1

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.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Can Joe-E be included in a Java program and be called and provided with code to verify? Or can it only be used in eclipse? Also, does it work well with Java 7, since it says it's currently for Java 6? Thanks. – contrapsych Dec 25 '13 at 05:31
  • Since it verifies source code instead of byte-code, I believe the changes to the Java 7 byte-code won't affect it, though it probably won't recognize new syntactic constructs like `<>`. Java 7 does introduce new APIs, and since Joe-E "tames" APIs the changes won't affect security, but those new APIs won't be available to untrusted code. Re Eclipse, I believe it can be run programmatically. You should ask that on the e-lang list. – Mike Samuel Dec 26 '13 at 02:04
1

White listing is the option. with blacklisting, attackers will find something malicious that is not black listed.

SecurityManager does the same by whitelisting the permissions. This is the way to go.

Code scanning may achieve the same at a different level, but you will reinvent the wheel(securitymanager)

Saran Makam
  • 126
  • 7
  • Actually SecurityManager only appears to whitelist permissions. Under the hood each function that do something dangerous will have to check that the caller has the proper permission. This have notoriously failed on multiple occasions. – user1657170 Sep 29 '14 at 14:17
0

Online judges do this. Some are open source. See if you can leverage either one of these or the code one is developed on. Googling, this product is open source and says the backend is in bash, which may help you with OS-interfacing security.

This judge looks like some random project that may or may not work or implement security, but it's Java. Keep Googling.

djechlin
  • 59,258
  • 35
  • 162
  • 290
0

I have looked into this matter. The standard Java security model are for each function that may do something dangerous, include code that checks the security privileges of the caller and deny access from someone within the sandbox. Additionally JNI can be disallowed in sandboxes code, for obvious reasons.

The problem with this approach are of course that sometimes developers forget to encapsulate their functions in security checks. Sometimes they do not even realize they create an insecure API and expect its dependencies to in turn deny access from sandboxed applications.

Another problem with this approach are that checking security violations within every API call are quite costly. In the past Java had other performance issues that made this quite low priority. For example the cost of a JNI call are usually so expensive that wrapping it in security code probably do very little to degrade performance. But modern JVM:s are so fast that this is probably becoming one of the mayor remaining bottlenecks.

I do not know how .NET implements sandboxing in modern versions. But I do i know how Mono and Native Client does it. Instead of having sandboxing within framework code they use pre-execution code inspection. They can then generate a class that only use secure API:s before it:s handed to the JIT. This of course ad a small delay to class loading but ends up more secure than the Java security model, and as a bonus there are a performance gain from now running a secure class without any sandboxing.

There are Java libraries that can be used to implement something similar in Java, such ASM and BCEL

The only attempt I can find to use code inspection in Java security are Mobile Code Security Through Java Byte-Code Modification which utilizes BECL for this.

user1657170
  • 318
  • 2
  • 7