In our recently begun study of the various available Java decompilers, we decided that a fair test of their abilities would be to attempt to decompile all 1669 class files in the Netscape Communicator 4.04 distribution. We could not resist the temptation to inspect some of their output to see if we could turn up holes for hostile applets. The following applets illustrate some problems that we found.
This nasty applet continuously dumps bytes to a file on your machine. How does it do that? In Communicator 4.05 there is a new package, netscape.secfile, that allows applets virtually unrestricted access to your hard drive under a "secure" directory, secfile in the browser's user.home directory. Applets like this make a mockery of the new package. Note that this applet does not announce its presence, and you might never know that it's filling up your file system - until it's too late. It's probably better not to try this one and just read the source code. A demo is available for those who insist.
We observed that the class sun.rmi.server.RMIClassLoader contains code that allows an applet to get and manipulate a ClassLoader. It seems possible for an applet to specify a URL and call RMIClassLoader.getClassLoader(URL url). If not checked by the Applet Security Manager, the applet will then have an RMIClassLoader, which can be cast to an AppletClassLoader. The key question then is whether or not the Communicator's Security Manager would stop the applet. We tried a little experiment and discovered that in fact it does not. We also observed that an applet can create a working AppletClassLoader directly by calling the constructor AppletClassLoader(URL url, null) in the class netscape.applet.AppletClassLoader. You can try this benign demonstration for yourself. You can also read the source code. Once you know how to have your applets create their own AppletClassLoaders, you can do your own experiments and see if you can create a type confusion attack.
We also observed that it is possible to employ AppletClassLoader(URL url, null) to construct fully functioning subclasses of AppletClassLoader. The applet MakeLoaders is an example which does so. This applet creates a devious ClassLoader that introduces a novel loadClass method, downloads a class Dummy from an alternative location, and runs code from the downloaded class. This is the simple technique that Vijay Saraswat used to construct type confusion examples in his recent paper. Pursuing this line of reasoning would lead us into the realm of attack applets of the sort introduced by the folks at Princeton over the last two years.
We also discovered two curious methods in the class netscape.misc.ObjectHeader:
public static native int GetObjectHeader(Object obj);
public static native int SetObjectHeader(Object obj, int i);
We could find no indiciation as to what these methods actually do, and we
could find no references to them in any other Java class files. So we
took the experimental approach and called them in an applet.
This is what the applet
looks like, and this
is what happens when you run it. This is perhaps a candidate for the
world's smallest hostile applet.
We also noticed that it is possible for an applet to directly manipulate the device field of the sun.audio.AudioDevice class. In particular, an unstoppable applet can lurk in the background and repreatedly call the class's close() method. This will prevent all other applets from playing audio clips and can even cause the Audio Player thread to exit. We created a little demo applet, and you can read the source code too if you're interested. This applet also works for the Internet Explorer 4.0.
We found that the class Principal allows any of its instances to have critical private fields read without going through any publicly accessible methods. To do so, one simply has to write the proper "encoder" class and pass it to the Principal.encode() method. As a simple demonstration, we applied the technique to theSystemPrincipal and used the information to construct an impostor, a Principal which is distinct from theSystemPrincipal and yet which is declared to be equal by the Principal.equals() method. The handy encoder is also worth a look.
This applet conspires with JavaScript to count the number of plugins that are installed with your Communicator and gives their full path names on your system. Note that JavaScript is allowed to do this, while Java applets alone are not. It then goes on to report how many entries are in your browser's history at the moment, though this is not supposed to be allowed. As always, you are welcome to read the source code and try out the applet.