by Michael 'mihi' Schierl, @mihi42
Oracle has released a patch now. Therefore, my unofficial patch is no longer available for download.
Not by me. At least not now. There is some good analysis available at Immunity, although I do not 100% agree to all of the conclusions drawn.
For issue 1, it is enough to add a checkPackageAccess call into MBeanInstantiator class. As there is a second place that instantiates classes (there is a third one in deserialize, but I am pretty confident classes created there cannot "leak"), I added a second call:
--- com/sun/jmx/mbeanserver/MBeanInstantiator.java.orig Sat Jan 12 19:57:00 2013 +++ com/sun/jmx/mbeanserver/MBeanInstantiator.java Sat Jan 12 20:10:20 2013 @@ -165,6 +165,7 @@ // Ok we do not have a primitive type ! We need to build // the signature of the method // + ReflectUtil.checkPackageAccess(signature[i]); if (aLoader != null) { // We need to load the class through the class // loader of the target object. @@ -626,6 +627,7 @@ IllegalArgumentException("The class name cannot be null"), "Exception occurred during object instantiation"); } + ReflectUtil.checkPackageAccess(className); try { if (loader == null) loader = MBeanInstantiator.class.getClassLoader();
Issue 2 is a bit different. Here I disagree with the Immunity opinion that the bug is in missing skipping of reflection classes. Reason is that the "new" reflection mechanism should by design not leave any trace in the stack trace, as it patches up the caller stack so that it looks as if the reflectively loaded method is called directly (and patching the CallSite so that if the same method is called again at the same place, it is much faster. Also speeding up the return case as fewer frames have to be popped). Apparently, this stack trace cleaning sometimes forgets a frame or two, so that issue should be fixed. But since this is in native code (as well as the stack walk to find the caller), it is not that easy to fix. Maybe for the same reason, MethodHandleNatives#isCallerSensitive was introduced in Java 7u9. Methods listed there will perform some more complex and slower caller binding to (hopefully) avoid this issue. However, all the Lookup.find* methods were not included here. So I patched it to include all the Lookup methods, and also include all the MethodHandles methods since the comment in getCallerClassAtEntryPoint suggests that they use the same mechanism:
*** java/lang/invoke/MethodHandleNatives.java.orig Wed Nov 28 04:42:18 2012 --- java/lang/invoke/MethodHandleNatives.java Sat Jan 12 19:55:20 2013 *************** *** 411,416 **** --- 411,418 ---- static boolean isCallerSensitive(MemberName mem) { assert(mem.isInvocable()); Class<?> defc = mem.getDeclaringClass(); + if (defc == MethodHandles.class || defc == Lookup.class) + return true; // better safe than sorry switch (mem.getName()) { case "doPrivileged": return defc == java.security.AccessController.class;
Most people do not like to recompile their JDK (or rebuild the rt.jar and the shared classes cache), but fortunately there is a (not very well documented and surely not intended for this use case) feature that if you have a jar file in jre/lib/endorsed folder, all class files in there will shadow class files of rt.jar. It was originally intended for updating XML parsers in Java 1.4 where it might have been needed more urgently than now, but it still works in Java 7.
Note that this patch will only work with Java 7 Update 10 (not Update 9 or any other Java version) and I won't take any responsibilities that it fixes the bug completely or that it won't break any other Java applications. I tested it with some exploits and it seemed to block them fine, though, and Eclipse still runs when using it :-)
Download Java7ZeroDay2013Buster1.jar (38 KB) No longer available, see above
Readme:
Java 7 2013 Zero Day 1 Buster by Michael 'mihi' Schierl, <schierlm at gmx.de>, http://schierlm.users.sourceforge.net/ To use, locate the (jre/)lib/security folder in your JDK/JRE (there should be a file called cacerts in it), create a folder (jre/)lib/endorsed next to it and place this Jar inside it. The Java VM will load all Jar files in this folder and replace any of its own runtime classes (from rt.jar) by .class files inside of these Jars. Note that this feature is not officially supported by Sun/Oracle except for updating XML parser libraries, but it seems to work. Use this Jar only for Java 7 Update 10, as other versions may have a different version of the patched class and break horribly. The patch seems to properly block the access vectors used by the 0day circulating at the moment, but I take no responsibility that it fixes all ways this bug can be exploited, nor that it will not break any other existing Java programs. The source code of the patched class is also included in the Jar file.