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:
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