Friday, March 8, 2013

Restrict signed Java applets


There's a ton of information on the Internet on how to sign Java applets and restrict unsigned Java applets as well. Very strangely there is very little information on doing the same for signed applets.

I did manage to find information which eventually helped me out; just that it took an insane amount of searching. Hence this little blog..which just collects all the information I found and puts it in 1 place.

First of all, the reason (as you already most probably know) to restrict signed applets, is that they're all powerful and can perform dangerous file I/O and network operations. So it's a nice thing to be able to restrict them from doing so, if needed. So here are the steps to do so, in a nutshell:

a) Sign your Java applet using keytool and jarsigner. A self signed applet is sufficient for demo purposes. The same logic can be used in case a trusted CA signs the certificate.

b) Once the applet is signed it's usually packaged into a JAR file prior to deploying it.

c) It's then deployed by embedding it into the HTML of a web page.

d) When the user visits the page, there's a pop-up which will now appear, asking the user to grant the applet additional permissions. Note here that if you click Run, the signed applet has complete control and can make numerous file and network I/O calls. If however, you click Cancel, you're not granting it permissions. The applet still runs (contrary to what one might intuitively think) but behaves like an unsigned applet.

e) What we now want to do though, is to limit what the applet can do, when the user clicks Run. For example: If all the user wants to do, is write to /tmp and nothing else, why should it have a million other privileges?

f) There's 2 ways to do it. One is to call every single relevant method in the applet from JavaScript. The second way is to write a policy in java.policy. Without frustrating you further, I'm going to show you, with a little sample code on how to do both.

g) First of all here is the Java code that I used as a POC. It's grabbed and tweaked from some tutorial online and not my own.


import java.applet.*;
import java.awt.*;
import java.io.* ;
import java.util.*;

public class FirstApplet extends Applet{
  public void init() {
    createFile("/abc/testsignapplet.txt");
  }
 
  public void test_HTMLbutton_method_invoke() {
    createFile("/abc/booboo.txt");
  }

  public void test_js_onload() {
    createFile("/abc/doodoo.txt");
  }

  private void createFile(String filename) {
    FileOutputStream out = null;
    try {
      out = new FileOutputStream(filename);
      out.write(("Testing jar signing process...:" + new Date()).getBytes());
    } catch(Exception ex) {
      ex.printStackTrace();
    } finally  {
      try {
        if(out != null) {
          out.close();
        }
      } catch(IOException e) {}
    }
  }
}

h) Here is how you must call the public methods of the applet from either an HTML element or from JavaScript. The line in the last < script > block which embeds the applet is possibly not the best way to do things; it's just there to show you guys how to call a method via HTML and JS, which is the point of the post.









i) Doing so, will cause the applet to still behave as an unsigned applet. If there's any malicious code in any of those functions, it's not going to be able to break out and cause havoc.

j) The other way of limiting the operations an applet can perform is by editing the file called java.policy. On a Ubuntu system, by default this file is inside your home directory. It is named .java.policy.

k) Back the file up and then delete all the lines in that file. Now add these lines to the file. This limits the applet loaded from http://localhost/applets/ from writing to any other directory except /abc.

grant codeBase "http://localhost/applets/*" {
  permission java.io.FilePermission "/abc/*", "write";
};

l) Note that a cool GUI tool called policytool can also be used for this purpose. If you have JRE or/and JDK on your machine, you should have policytool as well. You can add/edit/remove policies using it as well.

m) Test your applet using appletviewer first. It's a tool which you can use to check if your policies are working properly, before deploying the applets everywhere.

appletviewer -J-Djava.security.policy=/home/arvind/.java.policy sample.html

n) If the results are as expected, launch the applet in the browser. All the HTML and JS calls to methods should be blocked :)

----------
p.s - It's a good idea to have the Java Console launched while you're doing this stuff. It throws exceptions that you can then see and modify your approach accordingly. The Java Console can be launched using javaws -viewer and ticking 'Show Console' in the Advanced Tab.

Other Java related settings can be tweaked too in here. A good guide to follow can be found here - http://seanthegeek.github.com/harden-java/