Author Information
This technical article was written by Immunity's Chief Java Interrogator, Esteban (who you can follow: @sagar38)Introduction
Not so long ago Oracle released a new Java update [1] that included 30 security fixes. Many of those fixes appear to be the result of the research conducted by Security Explorations [3] who in turn informed Oracle. The research paper clearly explains the vulnerabilities discovered and some generic exploitation scenarios and techniques. Instead of analyzing the vulnerabilities we'll discuss something that is really interesting and was recently used in the JAX-WS exploit (CVE-2012-5076) that was found in the wild [4].This time besides killing bugs, Oracle also killed an “exploitation technique”.
We haven't seen any articles or papers explaining this technique, so now that it has been used in the wild and is publicly available, we think it is worth explaining in detail. This Oracle patch has changed a class that could be used to exploit a target if the right bug primitives were available. This technique will only work from JRE/JDK 7 up to JRE/JDK 7 update 7.
The technique explained here has been used in our two latest CANVAS Java exploits. And remember that if you want to learn this kind of Java stuff you can join us during the next Infiltrate at the Master Class being taught in part by Esteban!
Background
Is a well known fact that there are certain packages that are restricted when working with Applets. So any class inside sun.* package is a tempting destination if we have a vulnerability that bypasses the restrictions. Lets assume we have a couple of vulnerabilities which give us the primitives to:-
1) Create an instance of any class in any package (for example something in sun.*)
2) Call any public method on the instance we create, for example by using reflection and bypassing security checks.
Even if we have all that, we need to find a way of fully exploiting the target because having access to restricted packages doesn't mean we can just disable the Security Manager.
In 2010 Sami Koivu explained [5] a really cool vulnerability class that worked because a “Trusted execution chain” was built. The security checks were then passed simply because all the callers in the stack were part of the JDK and had enough permissions. The first question is “how do we start a trusted chain?”
The trick Koivu used to “start” the trusted execution chain was to create a javax.swing.JList instance, passing an object to it and then adding the instance to the applet. What happens then is that an AWT thread (that is trusted) would render that JList instance and would eventually call the toString() method on the object we put inside the JList.
It is important to keep Koivu's technique in mind because it will help to better understand part of the AnonymousClassLoader technique.
Analyzing the Patch
A quick diff performed against the two latest JDK 7 versions: update 7 and update 9 will show that there are a lot of changes to several classes in order to fix may vulnerabilities and one class that gets our attention is sun.invoke.anon.AnonymousClassLoader. The differences between these JDKs can be obtained for example using reJ tool [6], but we can also find the patch by taking a look at the OpenJDK repositories [7] [8].Although OpenJDK is not Sun's implementation it is really useful when auditing new JDK releases since parts of the Sun JDK source are not included in the releases. In the OpenJDK patch for CVE-2012-5088 [8] we can see the exact change made to the sun.invoke.anon.AnonymousClassLoader.
AnonymousClassLoader Technique
A curious thing to notice is that
although this class seems to be a “class loader” it does not
inherit from java.lang.ClassLoader. If we take a look at the
java.lang.ClassLoader type hierarchy, the AnonymousClassLoader is not
listed:
The changes made to this class show that its public constructors were removed together with other methods. We all know that ClassLoaders are important when it comes to exploitation so this “strange” class loader seems to be worth taking a look at.
According to its documentation and from what I've researched [9] [10] [11], this class does some weird things that will allow us (the attacker) to load classes that we can then use to bypass security checks. The classes that are loaded with AnonymousClassLoader appear not to be registered since this is not a normal class loader. The first thing we notice from the AnonymousClassLoader source code [12] is that it has an attribute called hostClass which is very important. The class documentation says:
If we take a look at the default constructor (the one without parameters), it calls sun.invoke.anon.AnonymousClassLoader.checkHostClass method with a null parameter. When that happens, the hostClass is set to the constructor's immediate caller. You can see this at the beginning of the checkHostClass implementation:
The changes made to this class show that its public constructors were removed together with other methods. We all know that ClassLoaders are important when it comes to exploitation so this “strange” class loader seems to be worth taking a look at.
According to its documentation and from what I've researched [9] [10] [11], this class does some weird things that will allow us (the attacker) to load classes that we can then use to bypass security checks. The classes that are loaded with AnonymousClassLoader appear not to be registered since this is not a normal class loader. The first thing we notice from the AnonymousClassLoader source code [12] is that it has an attribute called hostClass which is very important. The class documentation says:
The access permissions of the anonymous class are borrowed from a host class. The new class behaves as if it were an inner class of the host class. It can access the host's private members, if the creator of the class loader has permission to do so (or to create accessible reflective objects).Depending on the hostClass, the classes that we load with AnonymousClassLoader could possibly inherit privileged protection domains!
If we take a look at the default constructor (the one without parameters), it calls sun.invoke.anon.AnonymousClassLoader.checkHostClass method with a null parameter. When that happens, the hostClass is set to the constructor's immediate caller. You can see this at the beginning of the checkHostClass implementation:
private static Class<?> checkHostClass(Class<?> hostClass) { // called only from the constructor // does a context-sensitive check on caller class // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller} Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS); if (caller == null) { // called from the JVM directly if (hostClass == null) return AnonymousClassLoader.class; // anything central will do return hostClass; } if (hostClass == null) hostClass = caller; // default value is caller itself [...] }
This means that if the AnonymousClassLoader default constructor is called from any class that is part of the JDK, then its immediate caller will be considered trusted and hostClass will have privileged protection domains.
And more importantly, any class that we load with the AnonymousClassLoader instance will have a privileged protection domain and if we use this with Koivu's JList rendering trick to start a “Trusted execution chain” [5] we'll be able to disable the Security Manager.
What we can do now is make use of the public method sun.invoke.anon.AnonymousClassLoader.loadClass(byte[]) that receives a byte array containing a class (this is just a valid .class file that we read and store in a byte array or a class file from our JAR file that is obtained as a stream and converted to a byte array). This loadClass method will return a Class object and after that we can simply call objclass.newInstance() on it.
Remember we mentioned we need two primitives, so the first one would be used to create an instance of AnonymousClassLoader which is in sun.* and satisfies our first requirement.
What would probably happen with a vulnerability that provides such primitive is that the instance we get is an Object reference and unfortunately AnonymousClassLoader does not implement an interface so we don't have anything to easily call the “loadClass” method and a cast operation would just fail. This is where the second primitive comes in play!
As we mentioned before, if we wanted to call any method in this object variable we would need to cast it like this:
((AnonymousClassLoader)obj).loadClass(bytes);
This will not work! :(
The cast operation will raise an exception because we cannot access sun.invoke.anon package from the applet. If we simply tried to call getMethod/getMethod on the instance we have, we would also get the same exception.
So the second primitive would have to allow us to bypass the security checks and get a Method instance that is a reference to that loadClass public method we want to call. An example of a such primitive is one of the vulnerabilities used in the CVE-2012-4681 exploit [13].
Using this vulnerability as the second primitive we would obtain the method reference and load any class we wanted with the following piece of code where the “acl” variable is our AnonymousClassLoader instance created with the first primitive:
Class objclazz = acl.getClass(); Method m = com.sun.beans.finder.MethodFinder.findMethod(objclazz, "loadClass", byte[].class); smd_class = (Class) m.invoke(cl, smd_bytes); Object x = smd_class.newInstance();
What class should we load using this AnonymousClassLoader?
We need a fully trusted execution chain to disable the security manager and the only public trick that still works is the JList approach that calls a toString method on any object we pass it. We have to create a class with just a toString method that executes “System.setSecurityManager(null);”. Such a class is something as simple as this:
public class SecurityManagerDisabler { public String toString() { System.setSecurityManager(null); return ""; } }
That we compile that to generate a valid .class file and then read it to create a byte array we can hard-code in our exploit. This byte array would be the “smd_bytes” variable in the code snippet shown above when calling the loadClass method.
Once we have an instance of this class that disables the security manager we create a JList instance containing our object and add it to the applet so the AWT thread renders it and calls our toString method resulting in a trusted execution chain. The code to achieve this is just 2 lines (where “x” is this custom class instance we created in the previous code snippet):
JList l = new JList(new Object[] {x}); add(l);
This works and the complete call stack is trusted because our class was created with the AnonymousClassLoader and inherited the protection domain from a class that is part of the JDK.
An example of the complete stack call when using this technique would look like this:
Our custom class SecurityManagerDisabler is there and it has full privileges so the call to System.setSecurityManager will succeed.
An important thing to keep in mind about the AWT thread is that it may take a little bit until it effectively renders the Jlist object so we need to take this into consideration before executing our payload. One possibility is to launch another thread that sleeps for a bit and the executes the payload. Though we have to be careful not to call Thread.sleep directly in our applet init or start methods because the AWT thread may be delayed waiting for them.
Some of you may consider that using the JList trick is too much, so there is another more straight forward approach that can be used here. The class loaded with the AnonymousClassLoader could be something like this:
public class SecurityManagerDisabler implements PrivilegedExceptionAction { public SecurityManagerDisabler() { } public Object run() throws Exception { System.setSecurityManager(null); return null; } public String toString() { try { AccessController.doPrivileged(this); } catch (PrivilegedActionException e) {} return ""; } }
The difference here is that the class is implementing the interface PrivilegedExceptionAction and the toString method is using a doPrivileged block.
If you remember how the security checks are performed – which are clearly explained in the Secure Code Guidelines, section 9 [14] – when there is a doPrivileged block only the immediate caller is considered. So in this case, the immediate caller would be the SecurityManagerDisabler.toString method which has full privileges because we loaded the class with the AnonymousClassLoader allowing this way to perform any action. Now instead of creating the JList and adding our SecurityManagerDisabler instance we could directly call its toString method and everything will work just fine.
One important thing about the AnonymousClassLoader is that it is only available since JDK 7 and it has been moved to different packages in different versions [15]. JDK 7 included the class in package sun.dyn.anon but since JDK 7 update 1 the class is now included in package sun.invoke.anon, so one must be careful when targeting different JRE/JDK versions in order to get the AnonymousClassLoader from the right package.
References
- Java 7 update 9 release notes - http://www.oracle.com/technetwork/java/javase/7u9-relnotes-1863279.html
- Oracle Java SE Critical Patch Update Advisory - October 2012 - http://www.oracle.com/technetwork/topics/security/javacpuoct2012-1515924.html
- SE-2012-01 Security vulnerabilities in Java SE - http://www.security-explorations.com/en/SE-2012-01.html
- CVE-2012-5076 Java sample from "Cool" exploit pack - http://contagiodump.blogspot.com.ar/2012/11/cve-2012-5076-java-sample-from-cool.html
- Sami Koivu's Blog - Java Trusted Method Chaining (CVE-2010-0840/ZDI-10-056) - http://slightlyrandombrokenthoughts.blogspot.com.ar/2010/04/java-trusted-method-chaining-cve-, 2010.html
- reJ - http://rejava.sourceforge.net/
- CVE-2012-5088 OpenJDK: MethodHandle insufficient access control checks (Libraries, 7196190) - https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-5088
- 7196190: Improve method of handling MethodHandles - http://icedtea.classpath.org/hg/release/icedtea7-forest-2.3/jdk/rev/43113374306c
- Da Vinci project - http://openjdk.java.net/projects/mlvm/subprojects.html
- John Rose Oracle Blog entries: https://blogs.oracle.com/jrose/entry/notes_on_an_architecture_for, https://blogs.oracle.com/jrose/entry/dynamic_invocation_in_the_vm
- A First Taste of InvokeDynamic - http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html
- Sun.invoke.anon.AnonymousClassLoader - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/invoke/anon/AnonymousClassLoader.java#AnonymousClassLoader
- Java 0day analysis (CVE-2012-4681) - http://immunityproducts.blogspot.com/2012/08/java-0day-analysis-cve-2012-4681.html
- Secure Coding Guidelines for the Java Programming Language, Version 4.0 - http://www.oracle.com/technetwork/java/seccodeguide-139067.html#9
- Move JSR 292 to package java.lang.invoke and adjust names - http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2011-March/004961.html
No comments:
Post a Comment