Tuesday, 18 March 2008

Defeating the Same Origin Policy: Part II

In my last post I gave details of how unsigned applets could bypass the same origin policy in order to make arbitrary network connections; the Sun alert for this issue is here. In this post I'll wrap up my discussion of this bug, showing how it can be used to compromise the host.


Bypassing the Java same origin policy is dangerous in itself - not only could a malicious applet port scan the internal network of the host that instantiates it - it could also interact with and exploit the services it finds. However, in most cases, bypassing the same origin policy (at least in the browser) does not obviously lead to a direct compromise of the host. This particular flaw is different.


Extensions in Java are groups of packages and classes that augment the runtime classes. Extensions are installed into a specified directory and consequently can be located via the JRE without having to explicitly name them on the class path. QuickTime for Java is an example of a Java extension; once installed it enables Java applications to play QuickTime media (and yes, its had its share of security issues).


Moving on... take a look in your java.policy file (located in java.home\lib\security\java.policy) and you'll see where this attack is going. The first entry is most likely:


// Standard extensions get all permissions by default 

grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission; };


You'll remember from last time that by putting a URL in the code attribute allows an arbitrary codebase to specified. Thus if you use a codebase that references the extensions directory (e.g. "C:\Program Files\java\jre1.6.0_03\lib\ext") the applet is granted java.security.AllPermission. The Java documentation doesn't beat around the bush:


Granting AllPermission should be done with extreme care, as it implies all other permissions. Thus, it grants code the ability to run with security disabled. Extreme caution should be taken before granting such a permission to code. This permission should be used only during testing, or in extremely rare cases where an application or applet is completely trusted and adding the necessary permissions to the policy is prohibitively cumbersome.


The only thing left to do is come up with a reliable means of obtaining the path to the "JREx.y._zw\lib\ext" folder. The JRE version can be determined via querying the java.version property from a "bootstrapper" applet. Its probably safe to assume that on Windows platforms the JRE folder resides within the "Program Files\java" folder. As for the drive letter, the browser plugin prevents reading any properties that contain a path (so this rules out using java.home, java.class.path, user.name, user.home and user.dir). You could of course take a guess; "c:" is a pretty good candidate. There is one Windows-specific property, however, that can be read from an unsigned applet and that discloses a full path. The Windows Desktop Properties expose a win.xpstyle.dllName property that can be read as follows:


String dllName = (String)Toolkit.getDefaultToolkit().getDesktopProperty("win.xpstyle.dllName");


On my test box this returns "E:\WINDOWS\Resources\themes\Luna\Luna.msstyles".


So to conclude, the applet tag (which could obviously be generated dynamically) ends up looking like:


<APPLET code="http://2130706433/foo" codebase="file:E:\Program Files\java\jre1.6.0_03\lib\ext"/>


As for a payload, an applet with AllPermission can call Runtime.getRuntime().exec or System.loadLibrary to go straight to native code, fully compromising the browser.



Cheers

John

2 comments:

Anonymous said...

Very clever indeed :)

pdp said...

sweet! 10x